Skip to content

Commit f3b0809

Browse files
committed
apply spread only for dynamic dependencies
1 parent 099b6f0 commit f3b0809

File tree

4 files changed

+91
-25
lines changed

4 files changed

+91
-25
lines changed

src/compiler/compile/render_dom/wrappers/Element/index.ts

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -665,28 +665,45 @@ export default class ElementWrapper extends Wrapper {
665665
const initial_props = [];
666666
const updates = [];
667667

668+
const all_dependencies = new Set();
669+
this.attributes.forEach(attr => {
670+
add_to_set(all_dependencies, attr.node.get_dependencies());
671+
});
672+
668673
this.attributes
669674
.forEach(attr => {
670-
const condition = attr.node.dependencies.size > 0
671-
? block.renderer.dirty(Array.from(attr.node.dependencies))
675+
const dependencies = attr.node.get_dependencies();
676+
677+
const condition = dependencies.length > 0 && (dependencies.length !== all_dependencies.size)
678+
? block.renderer.dirty(dependencies)
672679
: null;
680+
const unchanged = dependencies.length === 0;
673681

682+
let snippet;
674683
if (attr.node.is_spread) {
675-
const snippet = attr.node.expression.manipulate(block);
684+
snippet = attr.node.expression.manipulate(block);
676685

677686
initial_props.push(snippet);
678687

679-
updates.push(condition ? x`${condition} && ${snippet}` : x`false`);
688+
if (attr.node.expression.node.type !== 'ObjectExpression') {
689+
snippet = x`@get_spread_object(${snippet})`;
690+
}
680691
} else {
681692
const metadata = attr.get_metadata();
682693
const name = attr.is_indirectly_bound_value()
683694
? '__value'
684695
: (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name);
685-
const snippet = x`{ ${name}: ${attr.get_value(block)} }`;
696+
snippet = x`{ ${name}: ${attr.get_value(block)} }`;
686697
initial_props.push(snippet);
687-
688-
updates.push(condition ? x`${condition} && ${snippet}` : x`false`);
689698
}
699+
700+
updates.push(
701+
unchanged
702+
? x`false`
703+
: condition
704+
? x`${condition} && ${snippet}`
705+
: snippet
706+
);
690707
});
691708

692709
block.chunks.init.push(b`
@@ -701,26 +718,22 @@ export default class ElementWrapper extends Wrapper {
701718
b`${fn}(${this.var}, ${data});`
702719
);
703720

704-
block.chunks.update.push(b`
705-
${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
706-
${updates}
707-
]));
708-
`);
721+
if (all_dependencies.size > 0) {
722+
block.chunks.update.push(b`
723+
if (${block.renderer.dirty(Array.from(all_dependencies))})
724+
${fn}(${this.var}, @get_spread_update(${levels}, [
725+
${updates}
726+
]));
727+
`);
728+
}
709729

710730
// handle edge cases for elements
711731
if (this.node.name === 'select') {
712-
const dependencies = new Set();
713-
for (const attr of this.attributes) {
714-
for (const dep of attr.node.dependencies) {
715-
dependencies.add(dep);
716-
}
717-
}
718-
719732
block.chunks.mount.push(b`
720733
if (${data}.multiple) @select_options(${this.var}, ${data}.value);
721734
`);
722735
block.chunks.update.push(b`
723-
if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
736+
if (${block.renderer.dirty(Array.from(all_dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
724737
`);
725738
}
726739
}

src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,17 @@ export default class InlineComponentWrapper extends Wrapper {
223223
const all_dependencies: Set<string> = new Set();
224224

225225
this.node.attributes.forEach(attr => {
226-
add_to_set(all_dependencies, attr.dependencies);
226+
add_to_set(all_dependencies, attr.get_dependencies());
227227
});
228228

229-
this.node.attributes.forEach((attr, i) => {
230-
const { name, dependencies } = attr;
229+
this.node.attributes.forEach((attr) => {
230+
const { name } = attr;
231+
const dependencies = attr.get_dependencies();
231232

232-
const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size)
233+
const condition = dependencies.length > 0 && (dependencies.length !== all_dependencies.size)
233234
? renderer.dirty(Array.from(dependencies))
234235
: null;
235-
const unchanged = dependencies.size === 0;
236+
const unchanged = dependencies.length === 0;
236237

237238
let change_object;
238239
if (attr.is_spread) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export default {
2+
props: {
3+
props: {
4+
foo: 'lol',
5+
baz: 40 + 2,
6+
}
7+
},
8+
9+
html: `
10+
<div baz="42" foo="lol" qux="named"></div>
11+
`,
12+
13+
test({ assert, component, target }) {
14+
const html = `
15+
<div qux="named"></div>
16+
`;
17+
18+
// test undefined
19+
component.props = undefined;
20+
assert.htmlEqual(target.innerHTML, html);
21+
22+
// set object props
23+
component.props = this.props.props;
24+
assert.htmlEqual(target.innerHTML, this.html);
25+
26+
// test null
27+
component.props = null;
28+
assert.htmlEqual(target.innerHTML, html);
29+
30+
// set object props
31+
component.props = this.props.props;
32+
assert.htmlEqual(target.innerHTML, this.html);
33+
34+
// test boolean
35+
component.props = true;
36+
assert.htmlEqual(target.innerHTML, html);
37+
38+
// set object props
39+
component.props = this.props.props;
40+
assert.htmlEqual(target.innerHTML, this.html);
41+
42+
// test number
43+
component.props = 123;
44+
assert.htmlEqual(target.innerHTML, html);
45+
46+
}
47+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
export let props;
3+
</script>
4+
5+
<div {...props} qux="named"/>

0 commit comments

Comments
 (0)