Repository: sveltejs/svelte (JavaScript)
Date: 2021-07-22 14:07:06+00:00
Task type: Bug Fix

Issue:
Reactivity / store regression in 3.39.0
### Describe the bug

Hi !

I noticed a regression from the 3.38.3 to the 3.39.0. When a store is defined inside an object, and given to a child component, this one is undefined if used with the $ sign in the script section. 

See the simple REPL for a better explanation 😃 

Thanks !

### Reproduction

You can reproduce the issue in this REPL : https://svelte.dev/repl/dcceadde29ce439886ffff8260f331a6?version=3.39.0

As you can see on the display, Inner store is undefined. This is due to the line
```
$: console.log('Inner store', $store);
```
in Child.svelte.

Commenting this line, and the example works again. It works with the 3.38.3.

### Logs

_No response_

### System Info

```shell
System:
    OS: Windows 10 10.0.18363
    CPU: (8) x64 Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
    Memory: 7.72 GB / 15.82 GB
  Binaries:
    Node: 16.5.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 7.20.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 91.0.4472.164
    Edge: Spartan (44.18362.1593.0)
    Internet Explorer: 11.0.18362.1
  npmPackages:
    rollup: ^2.3.4 => 2.53.3
    svelte: 3.39.0 => 3.39.0
```


### Severity

blocking an upgrade


Issue discussion:

Solution patch:
diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts
--- a/src/compiler/compile/Component.ts
+++ b/src/compiler/compile/Component.ts
@@ -666,8 +666,17 @@ export default class Component {
 			this.node_for_declaration.set(name, node);
 		});
 
-		globals.forEach((node, name) => {
+		// NOTE: add store variable first, then only $store value
+		// as `$store` will mark `store` variable as referenced and subscribable
+		const global_keys = Array.from(globals.keys());
+		const sorted_globals = [
+			...global_keys.filter(key => key[0] !== '$'),
+			...global_keys.filter(key => key[0] === '$')
+		];
+
+		sorted_globals.forEach(name => {
 			if (this.var_lookup.has(name)) return;
+			const node = globals.get(name);
 
 			if (this.injected_reactive_declaration_vars.has(name)) {
 				this.add_var({


Test patch:
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/App.svelte
@@ -0,0 +1,8 @@
+<script>
+	export let store_container;
+
+	$: ({ store } = store_container);
+	$: value = $store;
+</script>
+<div>{value}</div>
+<div>{$store}</div>
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/_config.js
@@ -0,0 +1,15 @@
+export default {
+	html: `
+		<div>Hello World</div>
+		<div>Hello World</div>
+	`,
+
+	async test({ assert, component, target, window }) {
+		await component.update_value('Hi Svelte');
+
+		assert.htmlEqual(target.innerHTML, `
+			<div>Hi Svelte</div>
+			<div>Hi Svelte</div>
+		`);
+	}
+};
diff --git a/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/store-auto-subscribe-in-reactive-declaration-2/main.svelte
@@ -0,0 +1,12 @@
+<script>
+	import { writable } from 'svelte/store';
+	import Child from './App.svelte';
+
+	const store_container = { store: writable('Hello World') };
+
+	export function update_value(value) {
+		store_container.store = writable(value);
+	}
+</script>
+
+<Child {store_container} />