Merge branch 'master' into dispatch-cancelable

pull/7064/head
bluwy 5 years ago
commit 5c0696dd79

2
.gitignore vendored

@ -16,8 +16,6 @@ node_modules
/transition
/animate
/scratch/
/coverage/
/coverage.lcov
/test/*/samples/_
/yarn-error.log
_actual*.*

@ -1,8 +1,10 @@
# Svelte changelog
## Unreleased
## 3.46.3
* Ignore whitespace in `{#each}` blocks when containing elements with `animate:` ([#5477](https://github.com/sveltejs/svelte/pull/5477))
* Throw compiler error when variable in `context="instance"` collides with import in `context="module"` ([#7090](https://github.com/sveltejs/svelte/issues/7090))
* Fix compiler crash when `{@const}` contains arrow functions ([#7134](https://github.com/sveltejs/svelte/issues/7134))
## 3.46.2

@ -0,0 +1,3 @@
This repository is governed by the Svelte Code of Conduct.
https://github.com/sveltejs/community/blob/main/CODE_OF_CONDUCT.md

690
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.46.2",
"version": "3.46.3",
"description": "Cybernetically enhanced web apps",
"module": "index.mjs",
"main": "index",
@ -86,10 +86,6 @@
"test": "mocha --exit",
"test:unit": "mocha --require sucrase/register --recursive src/**/__test__.ts --exit",
"quicktest": "mocha",
"precoverage": "c8 mocha",
"coverage": "c8 report --reporter=text-lcov > coverage.lcov && c8 report --reporter=html",
"codecov": "codecov",
"precodecov": "npm run coverage",
"build": "rollup -c && npm run tsd",
"prepare": "npm run build",
"dev": "rollup -cw",
@ -131,9 +127,7 @@
"@typescript-eslint/parser": "^4.31.2",
"acorn": "^8.4.1",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
"code-red": "^0.2.4",
"codecov": "^3.5.0",
"css-tree": "^1.1.2",
"eslint": "^7.32.0",
"eslint-plugin-import": "^2.24.2",

@ -213,6 +213,20 @@ Enforce that `on:mouseover` and `on:mouseout` are accompanied by `on:focus` and
---
### `a11y-no-redundant-roles`
Some HTML elements have default ARIA roles. Giving these elements an ARIA role that is already set by the browser [has no effect](https://www.w3.org/TR/using-aria/#aria-does-nothing) and is redundant.
```sv
<!-- A11y: Redundant role 'button' -->
<button role="button" />
<!-- A11y: Redundant role 'img' -->
<img role="img" src="foo.jpg" />
```
---
### `a11y-positive-tabindex`
Avoid positive `tabindex` property values. This will move elements out of the expected tab order, creating a confusing experience for keyboard users.

@ -4,14 +4,14 @@
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
let countValue;
const unsubscribe = count.subscribe(value => {
count_value = value;
countValue = value;
});
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {countValue}</h1>
<Incrementer/>
<Decrementer/>

@ -7,7 +7,7 @@
<svelte:window bind:scrollY={y}/>
<a class="parallax-container" href="https://www.firewatchgame.com">
{#each [0, 1, 2, 3, 4, 5, 6, 7, 8] as layer}
{#each layers as layer}
<img
style="transform: translate(0,{-y * layer / (layers.length - 1)}px)"
src="https://www.firewatchgame.com/images/parallax/parallax{layer}.png"
@ -85,4 +85,4 @@
padding: 0;
background-color: rgb(253, 174, 51);
}
</style>
</style>

@ -4,14 +4,14 @@
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
let countValue;
count.subscribe(value => {
count_value = value;
countValue = value;
});
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {countValue}</h1>
<Incrementer/>
<Decrementer/>

@ -4,14 +4,14 @@
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
let countValue;
count.subscribe(value => {
count_value = value;
countValue = value;
});
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {countValue}</h1>
<Incrementer/>
<Decrementer/>

@ -4,7 +4,7 @@ title: Writable stores
Not all application state belongs inside your application's component hierarchy. Sometimes, you'll have values that need to be accessed by multiple unrelated components, or by a regular JavaScript module.
In Svelte, we do this with *stores*. A store is simply an object with a `subscribe` method that allows interested parties to be notified whenever the store value changes. In `App.svelte`, `count` is a store, and we're setting `count_value` in the `count.subscribe` callback.
In Svelte, we do this with *stores*. A store is simply an object with a `subscribe` method that allows interested parties to be notified whenever the store value changes. In `App.svelte`, `count` is a store, and we're setting `countValue` in the `count.subscribe` callback.
Click the `stores.js` tab to see the definition of `count`. It's a *writable* store, which means it has `set` and `update` methods in addition to `subscribe`.

@ -4,14 +4,14 @@
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
let countValue;
count.subscribe(value => {
count_value = value;
countValue = value;
});
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {countValue}</h1>
<Incrementer/>
<Decrementer/>

@ -8,7 +8,7 @@ Start by declaring `unsubscribe` in `App.svelte`:
```js
const unsubscribe = count.subscribe(value => {
count_value = value;
countValue = value;
});
```
> Calling a `subscribe` method returns an `unsubscribe` function.
@ -23,16 +23,16 @@ You now declared `unsubscribe`, but it still needs to be called, for example thr
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
let countValue;
const unsubscribe = count.subscribe(value => {
count_value = value;
countValue = value;
});
onDestroy(unsubscribe);
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {countValue}</h1>
```
It starts to get a bit boilerplatey though, especially if your component subscribes to multiple stores. Instead, Svelte has a trick up its sleeve — you can reference a store value by prefixing the store name with `$`:

@ -191,27 +191,33 @@ export default class Component {
this.stylesheet.warn_on_unused_selectors(this);
}
add_var(variable: Var, add_to_lookup = true) {
add_var(node: Node, variable: Var, add_to_lookup = true) {
this.vars.push(variable);
if (add_to_lookup) {
if (this.var_lookup.has(variable.name)) {
const exists_var = this.var_lookup.get(variable.name);
if (exists_var.module && exists_var.imported) {
this.error(node as any, compiler_errors.illegal_variable_declaration);
}
}
this.var_lookup.set(variable.name, variable);
}
}
add_reference(name: string) {
add_reference(node: Node, name: string) {
const variable = this.var_lookup.get(name);
if (variable) {
variable.referenced = true;
} else if (is_reserved_keyword(name)) {
this.add_var({
this.add_var(node, {
name,
injected: true,
referenced: true
});
} else if (name[0] === '$') {
this.add_var({
this.add_var(node, {
name,
injected: true,
referenced: true,
@ -228,7 +234,7 @@ export default class Component {
}
} else {
if (this.compile_options.varsReport === 'full') {
this.add_var({ name, referenced: true }, false);
this.add_var(node, { name, referenced: true }, false);
}
this.used_names.add(name);
@ -599,12 +605,14 @@ export default class Component {
}
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
const imported = node.type.startsWith('Import');
this.add_var({
this.add_var(node, {
name,
module: true,
hoistable: true,
writable
writable,
imported
});
});
@ -612,7 +620,7 @@ export default class Component {
if (name[0] === '$') {
return this.error(node as any, compiler_errors.illegal_subscription);
} else {
this.add_var({
this.add_var(node, {
name,
global: true,
hoistable: true
@ -674,7 +682,7 @@ export default class Component {
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
const imported = node.type.startsWith('Import');
this.add_var({
this.add_var(node, {
name,
initialised: instance_scope.initialised_declarations.has(name),
writable,
@ -697,7 +705,7 @@ export default class Component {
const node = globals.get(name);
if (this.injected_reactive_declaration_vars.has(name)) {
this.add_var({
this.add_var(node, {
name,
injected: true,
writable: true,
@ -705,7 +713,7 @@ export default class Component {
initialised: true
});
} else if (is_reserved_keyword(name)) {
this.add_var({
this.add_var(node, {
name,
injected: true
});
@ -714,14 +722,14 @@ export default class Component {
return this.error(node as any, compiler_errors.illegal_global(name));
}
this.add_var({
this.add_var(node, {
name,
injected: true,
mutated: true,
writable: true
});
this.add_reference(name.slice(1));
this.add_reference(node, name.slice(1));
const variable = this.var_lookup.get(name.slice(1));
if (variable) {
@ -729,7 +737,7 @@ export default class Component {
variable.referenced_from_script = true;
}
} else {
this.add_var({
this.add_var(node, {
name,
global: true,
hoistable: true

@ -190,6 +190,10 @@ export default {
code: 'illegal-global',
message: `${name} is an illegal variable name`
}),
illegal_variable_declaration: {
code: 'illegal-variable-declaration',
message: 'Cannot declare same variable name which is imported inside <script context="module">'
},
cyclical_reactive_declaration: (cycle: string[]) => ({
code: 'cyclical-reactive-declaration',
message: `Cyclical dependency detected: ${cycle.join(' → ')}`

@ -18,7 +18,7 @@ export default class Action extends Node {
component.warn_if_undefined(object, info, scope);
this.name = info.name;
component.add_reference(object);
component.add_reference(this as any, object);
this.expression = info.expression
? new Expression(component, this, scope, info.expression)

@ -18,7 +18,7 @@ export default class Animation extends Node {
component.warn_if_undefined(info.name, info, scope);
this.name = info.name;
component.add_reference(info.name.split('.')[0]);
component.add_reference(this as any, info.name.split('.')[0]);
if (parent.animation) {
component.error(this, compiler_errors.duplicate_animation);

@ -29,7 +29,7 @@ export default class InlineComponent extends Node {
if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
const name = info.name.split('.')[0]; // accommodate namespaces
component.warn_if_undefined(name, info, scope);
component.add_reference(name);
component.add_reference(this as any, name);
}
this.name = info.name;
@ -141,10 +141,10 @@ export default class InlineComponent extends Node {
}
if (info.children.some(node => not_whitespace_text(node))) {
children.push({
children.push({
start: info.start,
end: info.end,
type: 'SlotTemplate',
type: 'SlotTemplate',
name: 'svelte:fragment',
attributes: [],
children: info.children

@ -19,7 +19,7 @@ export default class Transition extends Node {
component.warn_if_undefined(info.name, info, scope);
this.name = info.name;
component.add_reference(info.name.split('.')[0]);
component.add_reference(this as any, info.name.split('.')[0]);
this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
this.is_local = info.modifiers.includes('local');

@ -187,7 +187,7 @@ function mark_referenced(
if (is_reference(node, parent)) {
const { name } = flatten_reference(node);
if (!scope.is_let(name) && !scope.names.has(name)) {
component.add_reference(name);
component.add_reference(node, name);
}
}
}

@ -110,7 +110,7 @@ export default class Expression {
dependencies.add(name);
}
component.add_reference(name);
component.add_reference(node, name);
component.warn_if_undefined(name, nodes[0], template_scope);
}
@ -144,7 +144,7 @@ export default class Expression {
const each_block = template_scope.get_owner(name);
(each_block as EachBlock).has_binding = true;
} else {
component.add_reference(name);
component.add_reference(node, name);
const variable = component.var_lookup.get(name);
if (variable) variable[deep ? 'mutated' : 'reassigned'] = true;
@ -220,7 +220,7 @@ export default class Expression {
});
} else {
dependencies.add(name);
component.add_reference(name); // TODO is this redundant/misplaced?
component.add_reference(node, name); // TODO is this redundant/misplaced?
}
} else if (is_contextual(component, template_scope, name)) {
const reference = block.renderer.reference(node, ctx);
@ -253,13 +253,21 @@ export default class Expression {
const declaration = b`const ${id} = ${node}`;
if (dependencies.size === 0 && contextual_dependencies.size === 0) {
if (owner.type === 'ConstTag') {
walk(node, {
enter(node: Node) {
if (node.type === 'Identifier') {
this.replace(block.renderer.reference(node, ctx));
}
}
});
} else if (dependencies.size === 0 && contextual_dependencies.size === 0) {
// we can hoist this out of the component completely
component.fully_hoisted.push(declaration);
this.replace(id as any);
component.add_var({
component.add_var(node, {
name: id.name,
internal: true,
hoistable: true,

@ -264,7 +264,7 @@ export default class Renderer {
// TODO is this correct?
if (this.component.var_lookup.get(name)) {
this.component.add_reference(name);
this.component.add_reference(node, name);
}
if (member !== undefined) {

@ -0,0 +1,47 @@
export default {
html: `
<p>#FF0000</p>
<p>#00FF00</p>
<p>#0000FF</p>
`,
async test({ component, target, assert }) {
component.constant = 20;
assert.htmlEqual(target.innerHTML, `
<p>#FF0000</p>
<p>#00FF00</p>
<p>#0000FF</p>
`);
component.tags = [
{
name: 'Red',
color: '#FF0000'
},
{
name: 'Green',
color: '#00FF00'
},
{
name: 'Blue',
color: '#0000FF'
},
{
name: 'Black',
color: '#000000'
},
{
name: 'White',
color: '#FFFFFF'
}
];
assert.htmlEqual(target.innerHTML, `
<p>#FF0000</p>
<p>#00FF00</p>
<p>#0000FF</p>
<p>#000000</p>
<p>#FFFFFF</p>
`);
}
};

@ -0,0 +1,21 @@
<script>
export let tags = [
{
name: 'Red',
color: '#FF0000'
},
{
name: 'Green',
color: '#00FF00'
},
{
name: 'Blue',
color: '#0000FF'
}
];
</script>
{#each tags as tag}
{@const tagColor = tags.find(t => t.name === tag.name).color}
<p>{tagColor}</p>
{/each}

@ -0,0 +1,17 @@
[
{
"code": "illegal-variable-declaration",
"message": "Cannot declare same variable name which is imported inside <script context=\"module\">",
"start": {
"line": 6,
"column": 1,
"character": 86
},
"end": {
"line": 6,
"column": 9,
"character": 94
},
"pos": 86
}
]

@ -0,0 +1,9 @@
<script context="module">
import { FOO } from './dummy.svelte';
</script>
<script>
let FOO;
</script>
{FOO}
Loading…
Cancel
Save