Skip to content

Commit

Permalink
fix mutation to imported variable (sveltejs#4713)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanhauhau committed Apr 24, 2020
1 parent 676d57b commit aabb23c
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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))
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
});

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down
3 changes: 3 additions & 0 deletions test/runtime/samples/reactive-import-statement-2/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
html: `<p>prop value</p>`
};
3 changes: 3 additions & 0 deletions test/runtime/samples/reactive-import-statement-2/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const obj = {
prop: 'prop value'
};
8 changes: 8 additions & 0 deletions test/runtime/samples/reactive-import-statement-2/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
import { obj } from './data.js';
$: prop = obj.prop;
obj.foo = 'a different prop';
</script>

<p>{prop}</p>
38 changes: 38 additions & 0 deletions test/runtime/samples/reactive-import-statement/_config.js
Original file line number Diff line number Diff line change
@@ -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>
`);
}
};
1 change: 1 addition & 0 deletions test/runtime/samples/reactive-import-statement/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const numbers = [1, 2, 3, 4];
19 changes: 19 additions & 0 deletions test/runtime/samples/reactive-import-statement/main.svelte
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit aabb23c

Please sign in to comment.