fix mutation to imported variable (#4713)

pull/4719/head
Tan Li Hau 4 years ago committed by GitHub
parent 676d57b5f7
commit aabb23cc34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,9 @@
# Svelte changelog # Svelte changelog
## Unreleased
* Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555))
## 3.21.0 ## 3.21.0
* Support dimension bindings in cross-origin environments ([#2147](https://github.com/sveltejs/svelte/issues/2147)) * Support dimension bindings in cross-origin environments ([#2147](https://github.com/sveltejs/svelte/issues/2147))

@ -632,7 +632,6 @@ export default class Component {
this.add_var({ this.add_var({
name, name,
initialised: instance_scope.initialised_declarations.has(name), initialised: instance_scope.initialised_declarations.has(name),
hoistable: /^Import/.test(node.type),
writable writable
}); });
@ -986,6 +985,7 @@ export default class Component {
hoistable_nodes, hoistable_nodes,
var_lookup, var_lookup,
injected_reactive_declaration_vars, injected_reactive_declaration_vars,
imports,
} = this; } = this;
const top_level_function_declarations = new Map(); const top_level_function_declarations = new Map();
@ -1137,6 +1137,14 @@ export default class Component {
this.fully_hoisted.push(node); 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() { extract_reactive_declarations() {

@ -0,0 +1,3 @@
export default {
html: `<p>prop value</p>`
};

@ -0,0 +1,3 @@
export const obj = {
prop: 'prop value'
};

@ -0,0 +1,8 @@
<script>
import { obj } from './data.js';
$: prop = obj.prop;
obj.foo = 'a different prop';
</script>
<p>{prop}</p>

@ -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>
`);
}
};

@ -0,0 +1 @@
export const numbers = [1, 2, 3, 4];

@ -0,0 +1,19 @@
<script>
import { numbers } 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>
Loading…
Cancel
Save