From 6f3d7beaae00910eec831127b76fd848f94135b0 Mon Sep 17 00:00:00 2001 From: Tan Li Hau <lhtan93@gmail.com> Date: Fri, 24 Apr 2020 08:13:25 +0800 Subject: [PATCH 1/4] fix mutation to imported variable --- src/compiler/compile/Component.ts | 10 ++++- .../reactive-import-statement-2/_config.js | 5 +++ .../reactive-import-statement-2/data.js | 3 ++ .../reactive-import-statement-2/main.svelte | 8 ++++ .../reactive-import-statement/_config.js | 38 +++++++++++++++++++ .../samples/reactive-import-statement/data.js | 1 + .../reactive-import-statement/main.svelte | 19 ++++++++++ 7 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/reactive-import-statement-2/_config.js create mode 100644 test/runtime/samples/reactive-import-statement-2/data.js create mode 100644 test/runtime/samples/reactive-import-statement-2/main.svelte create mode 100644 test/runtime/samples/reactive-import-statement/_config.js create mode 100644 test/runtime/samples/reactive-import-statement/data.js create mode 100644 test/runtime/samples/reactive-import-statement/main.svelte diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index bb1546ceee9c..c83f8153a01e 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -632,7 +632,6 @@ export default class Component { this.add_var({ name, initialised: instance_scope.initialised_declarations.has(name), - hoistable: /^Import/.test(node.type), writable }); @@ -986,6 +985,7 @@ export default class Component { hoistable_nodes, var_lookup, injected_reactive_declaration_vars, + imports, } = this; const top_level_function_declarations = new Map(); @@ -1137,6 +1137,14 @@ export default class Component { this.fully_hoisted.push(node); } } + + for (const { specifiers } of imports) { + for (const specifier of specifiers) { + const variable = var_lookup.get(specifier.local.name); + + if (!variable.mutated) variable.hoistable = true; + } + } } extract_reactive_declarations() { diff --git a/test/runtime/samples/reactive-import-statement-2/_config.js b/test/runtime/samples/reactive-import-statement-2/_config.js new file mode 100644 index 000000000000..03b5b97e6e2e --- /dev/null +++ b/test/runtime/samples/reactive-import-statement-2/_config.js @@ -0,0 +1,5 @@ +export default { + html: ` + Im a prop + `, +}; diff --git a/test/runtime/samples/reactive-import-statement-2/data.js b/test/runtime/samples/reactive-import-statement-2/data.js new file mode 100644 index 000000000000..28c7c656026f --- /dev/null +++ b/test/runtime/samples/reactive-import-statement-2/data.js @@ -0,0 +1,3 @@ +export const obj = { + prop: 'Im a prop' +}; \ No newline at end of file diff --git a/test/runtime/samples/reactive-import-statement-2/main.svelte b/test/runtime/samples/reactive-import-statement-2/main.svelte new file mode 100644 index 000000000000..4f6f0abf6fa7 --- /dev/null +++ b/test/runtime/samples/reactive-import-statement-2/main.svelte @@ -0,0 +1,8 @@ +<script> + import { obj } from './data.js' + + $: prop = obj.prop + obj.foo = 'uncomment this line to break the example' +</script> + +{prop} diff --git a/test/runtime/samples/reactive-import-statement/_config.js b/test/runtime/samples/reactive-import-statement/_config.js new file mode 100644 index 000000000000..7fb8097ca58a --- /dev/null +++ b/test/runtime/samples/reactive-import-statement/_config.js @@ -0,0 +1,38 @@ +import * as path from 'path'; + +export default { + html: ` + import + <p>1 + 2 + 3 + 4 = 10</p> + local + <p>1 + 2 + 3 + 4 = 10</p> + <button>Add a number</button> + `, + before_test() { + delete require.cache[path.resolve(__dirname, 'data.js')]; + }, + async test({ assert, target, window, }) { + const btn = target.querySelector('button'); + const clickEvent = new window.MouseEvent('click'); + + await btn.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` + import + <p>1 + 2 + 3 + 4 + 5 = 15</p> + local + <p>1 + 2 + 3 + 4 + 5 = 15</p> + <button>Add a number</button> + `); + + await btn.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` + import + <p>1 + 2 + 3 + 4 + 5 + 6 = 21</p> + local + <p>1 + 2 + 3 + 4 + 5 + 6 = 21</p> + <button>Add a number</button> + `); + } +}; diff --git a/test/runtime/samples/reactive-import-statement/data.js b/test/runtime/samples/reactive-import-statement/data.js new file mode 100644 index 000000000000..ad494c7cb04b --- /dev/null +++ b/test/runtime/samples/reactive-import-statement/data.js @@ -0,0 +1 @@ +export const numbers = [1, 2, 3, 4]; \ No newline at end of file diff --git a/test/runtime/samples/reactive-import-statement/main.svelte b/test/runtime/samples/reactive-import-statement/main.svelte new file mode 100644 index 000000000000..0ee627002447 --- /dev/null +++ b/test/runtime/samples/reactive-import-statement/main.svelte @@ -0,0 +1,19 @@ +<script> + import {numbers, foo} from './data.js' + const local_numbers = [1, 2, 3, 4]; + + function addNumber() { + numbers[numbers.length] = numbers.length + 1; + local_numbers[local_numbers.length] = local_numbers.length + 1; + } + + $: sum = numbers.reduce((t, n) => t + n, 0); + $: local_sum = local_numbers.reduce((t, n) => t + n, 0); +</script> + +import <p>{numbers.join(' + ')} = {sum}</p> +local <p>{local_numbers.join(' + ')} = {local_sum}</p> + +<button on:click={addNumber}> + Add a number +</button> \ No newline at end of file From f7b63203105dd52f1a97e4bcdf952606c73f19c8 Mon Sep 17 00:00:00 2001 From: Conduitry <git@chor.date> Date: Fri, 24 Apr 2020 12:56:27 -0400 Subject: [PATCH 2/4] adjust test --- .../samples/reactive-import-statement-2/_config.js | 4 +--- .../samples/reactive-import-statement-2/data.js | 4 ++-- .../samples/reactive-import-statement-2/main.svelte | 10 +++++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/test/runtime/samples/reactive-import-statement-2/_config.js b/test/runtime/samples/reactive-import-statement-2/_config.js index 03b5b97e6e2e..ccc97cd076b2 100644 --- a/test/runtime/samples/reactive-import-statement-2/_config.js +++ b/test/runtime/samples/reactive-import-statement-2/_config.js @@ -1,5 +1,3 @@ export default { - html: ` - Im a prop - `, + html: `<p>prop value</p>` }; diff --git a/test/runtime/samples/reactive-import-statement-2/data.js b/test/runtime/samples/reactive-import-statement-2/data.js index 28c7c656026f..56fb86982c77 100644 --- a/test/runtime/samples/reactive-import-statement-2/data.js +++ b/test/runtime/samples/reactive-import-statement-2/data.js @@ -1,3 +1,3 @@ export const obj = { - prop: 'Im a prop' -}; \ No newline at end of file + prop: 'prop value' +}; diff --git a/test/runtime/samples/reactive-import-statement-2/main.svelte b/test/runtime/samples/reactive-import-statement-2/main.svelte index 4f6f0abf6fa7..2582974b71b3 100644 --- a/test/runtime/samples/reactive-import-statement-2/main.svelte +++ b/test/runtime/samples/reactive-import-statement-2/main.svelte @@ -1,8 +1,8 @@ <script> - import { obj } from './data.js' - - $: prop = obj.prop - obj.foo = 'uncomment this line to break the example' + import { obj } from './data.js'; + + $: prop = obj.prop; + obj.foo = 'a different prop'; </script> -{prop} +<p>{prop}</p> From 46cc8180996b79614accd0718e2368868fe9c7ec Mon Sep 17 00:00:00 2001 From: Conduitry <git@chor.date> Date: Fri, 24 Apr 2020 12:58:04 -0400 Subject: [PATCH 3/4] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9b3bb8b9a2b..3fceb5f2fc16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555)) + ## 3.21.0 * Support dimension bindings in cross-origin environments ([#2147](https://github.com/sveltejs/svelte/issues/2147)) From bfc91c9b00b8632b5b68200627b47f758a6d6ca4 Mon Sep 17 00:00:00 2001 From: Conduitry <git@chor.date> Date: Fri, 24 Apr 2020 13:01:51 -0400 Subject: [PATCH 4/4] lint other test --- test/runtime/samples/reactive-import-statement/main.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtime/samples/reactive-import-statement/main.svelte b/test/runtime/samples/reactive-import-statement/main.svelte index 0ee627002447..daded0494f4b 100644 --- a/test/runtime/samples/reactive-import-statement/main.svelte +++ b/test/runtime/samples/reactive-import-statement/main.svelte @@ -1,5 +1,5 @@ <script> - import {numbers, foo} from './data.js' + import { numbers } from './data.js'; const local_numbers = [1, 2, 3, 4]; function addNumber() {