Skip to content

Commit f739b47

Browse files
authored
error on expression scope store (#5079)
1 parent e6026fe commit f739b47

File tree

7 files changed

+45
-8
lines changed

7 files changed

+45
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Do not display `a11y-missing-content` warning on elements with `contenteditable` bindings ([#5020](https://github.com/sveltejs/svelte/issues/5020))
1010
* Fix handling of `this` in inline function expressions in the template ([#5033](https://github.com/sveltejs/svelte/issues/5033))
1111
* Fix collapsing HTML with static content ([#5040](https://github.com/sveltejs/svelte/issues/5040))
12+
* Prevent use of `$store` at compile time when top-level `store` has been shadowed ([#5048](https://github.com/sveltejs/svelte/issues/5048))
1213
* Update `<select>` with one-way `value` binding when the available `<option>`s change ([#5051](https://github.com/sveltejs/svelte/issues/5051))
1314
* Fix published `tweened` types so the `.set()` and `.update()` options are optional ([#5062](https://github.com/sveltejs/svelte/issues/5062))
1415
* Fix contextual `bind:this` inside `{#each}` block ([#5067](https://github.com/sveltejs/svelte/issues/5067))

src/compiler/compile/Component.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ export default class Component {
836836
});
837837
}
838838

839-
warn_on_undefined_store_value_references(node, parent, scope) {
839+
warn_on_undefined_store_value_references(node, parent, scope: Scope) {
840840
if (
841841
node.type === 'LabeledStatement' &&
842842
node.label.name === '$' &&
@@ -852,8 +852,17 @@ export default class Component {
852852
const object = get_object(node);
853853
const { name } = object;
854854

855-
if (name[0] === '$' && !scope.has(name)) {
856-
this.warn_if_undefined(name, object, null);
855+
if (name[0] === '$') {
856+
if (!scope.has(name)) {
857+
this.warn_if_undefined(name, object, null);
858+
}
859+
860+
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
861+
this.error(node, {
862+
code: `contextual-store`,
863+
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
864+
});
865+
}
857866
}
858867
}
859868
}

src/compiler/compile/nodes/shared/Expression.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,14 @@ export default class Expression {
7878

7979
if (scope.has(name)) return;
8080

81-
if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
82-
component.error(node, {
83-
code: `contextual-store`,
84-
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
85-
});
81+
if (name[0] === '$') {
82+
const store_name = name.slice(1);
83+
if (template_scope.names.has(store_name) || scope.has(store_name)) {
84+
component.error(node, {
85+
code: `contextual-store`,
86+
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
87+
});
88+
}
8689
}
8790

8891
if (template_scope.is_let(name)) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
error: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
3+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
import { writable } from 'svelte/store';
3+
const store = writable();
4+
5+
function foo() {
6+
let store = 1;
7+
$store = 2;
8+
}
9+
</script>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
error: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
3+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
import { writable } from 'svelte/store';
3+
const store = writable();
4+
</script>
5+
6+
<button
7+
on:click={(store) => {
8+
$store = Math.random();
9+
}} />

0 commit comments

Comments
 (0)