Skip to content

Commit ed72aea

Browse files
authored
Merge pull request #2865 from sveltejs/less-invalidation
only invalidate referenced values
2 parents 60a2a51 + e8b769c commit ed72aea

File tree

11 files changed

+152
-27
lines changed

11 files changed

+152
-27
lines changed

src/compile/Component.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,10 @@ export default class Component {
789789
return `${name.slice(1)}.set(${name})`
790790
}
791791

792+
if (variable && !variable.referenced && !variable.is_reactive_dependency && !variable.export_name && !name.startsWith('$$')) {
793+
return value || name;
794+
}
795+
792796
if (value) {
793797
return `$$invalidate('${name}', ${value})`;
794798
}
@@ -1120,8 +1124,9 @@ export default class Component {
11201124
if (!assignee_nodes.has(identifier)) {
11211125
const { name } = identifier;
11221126
const owner = scope.find_owner(name);
1123-
const component_var = component.var_lookup.get(name);
1124-
const is_writable_or_mutated = component_var && (component_var.writable || component_var.mutated);
1127+
const variable = component.var_lookup.get(name);
1128+
if (variable) variable.is_reactive_dependency = true;
1129+
const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
11251130
if (
11261131
(!owner || owner === component.instance_scope) &&
11271132
(name[0] === '$' || is_writable_or_mutated)

src/compile/render-dom/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,10 @@ export default function dom(
203203
if (variable && (variable.hoistable || variable.global || variable.module)) return;
204204

205205
if (single && !(variable.subscribable && variable.reassigned)) {
206-
code.prependRight(node.start, `$$invalidate('${name}', `);
207-
code.appendLeft(node.end, `)`);
206+
if (variable.referenced || variable.is_reactive_dependency || variable.export_name) {
207+
code.prependRight(node.start, `$$invalidate('${name}', `);
208+
code.appendLeft(node.end, `)`);
209+
}
208210
} else {
209211
pending_assignments.add(name);
210212
}

src/interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,5 @@ export interface Var {
133133
initialised?: boolean;
134134
hoistable?: boolean;
135135
subscribable?: boolean;
136-
}
136+
is_reactive_dependency?: boolean;
137+
}

test/js/samples/reactive-values-non-topologically-ordered/expected.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function instance($$self, $$props, $$invalidate) {
2929

3030
$$self.$$.update = ($$dirty = { x: 1, b: 1 }) => {
3131
if ($$dirty.x) { $$invalidate('b', b = x); }
32-
if ($$dirty.b) { $$invalidate('a', a = b); }
32+
if ($$dirty.b) { a = b; }
3333
};
3434

3535
return { x };

test/js/samples/reactive-values-non-writable-dependencies/expected.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,25 @@ function create_fragment(ctx) {
1717
};
1818
}
1919

20-
let a = 1;
21-
22-
let b = 2;
23-
2420
function instance($$self, $$props, $$invalidate) {
25-
21+
let { a = 1, b = 2 } = $$props;
2622

27-
let max;
23+
$$self.$set = $$props => {
24+
if ('a' in $$props) $$invalidate('a', a = $$props.a);
25+
if ('b' in $$props) $$invalidate('b', b = $$props.b);
26+
};
2827

2928
$$self.$$.update = ($$dirty = { a: 1, b: 1 }) => {
30-
if ($$dirty.a || $$dirty.b) { $$invalidate('max', max = Math.max(a, b)); }
29+
if ($$dirty.a || $$dirty.b) { console.log('max', Math.max(a, b)); }
3130
};
3231

33-
return {};
32+
return { a, b };
3433
}
3534

3635
class Component extends SvelteComponent {
3736
constructor(options) {
3837
super();
39-
init(this, options, instance, create_fragment, safe_not_equal, []);
38+
init(this, options, instance, create_fragment, safe_not_equal, ["a", "b"]);
4039
}
4140
}
4241

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script>
2-
let a = 1;
3-
let b = 2;
2+
export let a = 1;
3+
export let b = 2;
44
5-
let max;
6-
$: max = Math.max(a, b);
5+
$: console.log('max', Math.max(a, b));
76
</script>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* generated by Svelte vX.Y.Z */
2+
import {
3+
SvelteComponent,
4+
append,
5+
detach,
6+
element,
7+
init,
8+
insert,
9+
noop,
10+
safe_not_equal,
11+
set_data,
12+
text
13+
} from "svelte/internal";
14+
import { onMount } from "svelte";
15+
16+
function create_fragment(ctx) {
17+
var p, t;
18+
19+
return {
20+
c() {
21+
p = element("p");
22+
t = text(ctx.y);
23+
},
24+
25+
m(target, anchor) {
26+
insert(target, p, anchor);
27+
append(p, t);
28+
},
29+
30+
p(changed, ctx) {
31+
if (changed.y) {
32+
set_data(t, ctx.y);
33+
}
34+
},
35+
36+
i: noop,
37+
o: noop,
38+
39+
d(detaching) {
40+
if (detaching) {
41+
detach(p);
42+
}
43+
}
44+
};
45+
}
46+
47+
function instance($$self, $$props, $$invalidate) {
48+
let a, b, c;
49+
50+
onMount(() => {
51+
const interval = setInterval(() => {
52+
$$invalidate('b', b += 1);
53+
c += 1;
54+
55+
console.log(b, c);
56+
}, 1000);
57+
58+
return () => clearInterval(interval);
59+
});
60+
61+
let x, y;
62+
63+
$$self.$$.update = ($$dirty = { a: 1, b: 1 }) => {
64+
if ($$dirty.a) { x = a * 2; }
65+
if ($$dirty.b) { $$invalidate('y', y = b * 2); }
66+
};
67+
68+
return { y };
69+
}
70+
71+
class Component extends SvelteComponent {
72+
constructor(options) {
73+
super();
74+
init(this, options, instance, create_fragment, safe_not_equal, []);
75+
}
76+
}
77+
78+
export default Component;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script>
2+
import { onMount } from 'svelte';
3+
4+
let a, b, c;
5+
6+
onMount(() => {
7+
const interval = setInterval(() => {
8+
b += 1;
9+
c += 1;
10+
11+
console.log(b, c);
12+
}, 1000);
13+
14+
return () => clearInterval(interval);
15+
});
16+
17+
$: x = a * 2;
18+
$: y = b * 2;
19+
</script>
20+
21+
<p>{y}</p>

test/runtime/samples/immutable-nested/Nested.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script>
22
import { beforeUpdate, onMount } from 'svelte';
33
4-
let mounted;
4+
let mounted = false;
55
export let count = 0;
66
export let foo = { bar: 'baz' };
77
@@ -14,4 +14,5 @@
1414
});
1515
</script>
1616

17-
<h3>Called {count} times.</h3>
17+
<h3>Called {count} times.</h3>
18+
<p>{foo.bar} {mounted}</p>
Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
export default {
22
immutable: true,
33

4-
html: `<div><h3>Called 1 times.</h3></div>`,
4+
html: `
5+
<div>
6+
<h3>Called 1 times.</h3>
7+
<p>baz true</p>
8+
</div>
9+
`,
510

6-
ssrHtml: `<div><h3>Called 0 times.</h3></div>`,
11+
ssrHtml: `
12+
<div>
13+
<h3>Called 0 times.</h3>
14+
<p>baz false</p>
15+
</div>`,
716

8-
test({ assert, component, target, window }) {
17+
test({ assert, component, target }) {
918
var nested = component.nested;
1019

11-
assert.htmlEqual(target.innerHTML, `<div><h3>Called 1 times.</h3></div>`);
20+
assert.htmlEqual(target.innerHTML, `
21+
<div>
22+
<h3>Called 1 times.</h3>
23+
<p>baz true</p>
24+
</div>
25+
`);
1226

1327
nested.foo = nested.foo;
14-
assert.htmlEqual(target.innerHTML, `<div><h3>Called 1 times.</h3></div>`);
28+
assert.htmlEqual(target.innerHTML, `
29+
<div>
30+
<h3>Called 1 times.</h3>
31+
<p>baz true</p>
32+
</div>
33+
`);
1534
}
1635
};

test/runtime/samples/immutable-nested/main.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
</script>
66

77
<div>
8-
<Nested bind:this={nested} />
8+
<Nested bind:this={nested} />
99
</div>

0 commit comments

Comments
 (0)