apply spread only for dynamic dependencies

pull/4896/head
Tan Li Hau 5 years ago
parent 099b6f002a
commit 9f0b6781f1

@ -665,28 +665,45 @@ export default class ElementWrapper extends Wrapper {
const initial_props = []; const initial_props = [];
const updates = []; const updates = [];
const all_dependencies = new Set();
this.attributes.forEach(attr => {
add_to_set(all_dependencies, attr.node.get_dependencies());
});
this.attributes this.attributes
.forEach(attr => { .forEach(attr => {
const condition = attr.node.dependencies.size > 0 const dependencies = attr.node.get_dependencies();
? block.renderer.dirty(Array.from(attr.node.dependencies))
const condition = dependencies.length > 0 && (dependencies.length !== all_dependencies.size)
? block.renderer.dirty(dependencies)
: null; : null;
const unchanged = dependencies.length === 0;
let snippet;
if (attr.node.is_spread) { if (attr.node.is_spread) {
const snippet = attr.node.expression.manipulate(block); snippet = attr.node.expression.manipulate(block);
initial_props.push(snippet); initial_props.push(snippet);
updates.push(condition ? x`${condition} && ${snippet}` : x`false`); if (attr.node.expression.node.type !== 'ObjectExpression') {
snippet = x`@get_spread_object(${snippet})`;
}
} else { } else {
const metadata = attr.get_metadata(); const metadata = attr.get_metadata();
const name = attr.is_indirectly_bound_value() const name = attr.is_indirectly_bound_value()
? '__value' ? '__value'
: (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name); : (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name);
const snippet = x`{ ${name}: ${attr.get_value(block)} }`; snippet = x`{ ${name}: ${attr.get_value(block)} }`;
initial_props.push(snippet); initial_props.push(snippet);
updates.push(condition ? x`${condition} && ${snippet}` : x`false`);
} }
updates.push(
unchanged
? x`false`
: condition
? x`${condition} && ${snippet}`
: snippet
);
}); });
block.chunks.init.push(b` block.chunks.init.push(b`
@ -701,27 +718,29 @@ export default class ElementWrapper extends Wrapper {
b`${fn}(${this.var}, ${data});` b`${fn}(${this.var}, ${data});`
); );
block.chunks.update.push(b` const need_update_data = this.node.name === 'select';
${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [
${updates}
]));
`);
// handle edge cases for elements if (all_dependencies.size > 0) {
if (this.node.name === 'select') { block.chunks.update.push(b`
const dependencies = new Set(); if (${block.renderer.dirty(Array.from(all_dependencies))}) {
for (const attr of this.attributes) { ${fn}(${this.var}, @get_spread_update(${levels}, [
for (const dep of attr.node.dependencies) { ${updates}
dependencies.add(dep); ]));
${need_update_data && b`${data} = @get_attributes_for_spread(${levels});`}
} }
} `);
}
// handle edge cases for elements
if (this.node.name === 'select') {
block.chunks.mount.push(b` block.chunks.mount.push(b`
if (${data}.multiple) @select_options(${this.var}, ${data}.value); if (${data}.multiple) @select_options(${this.var}, ${data}.value);
`); `);
block.chunks.update.push(b` if (all_dependencies.size > 0) {
if (${block.renderer.dirty(Array.from(dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value); block.chunks.update.push(b`
`); if (${block.renderer.dirty(Array.from(all_dependencies))} && ${data}.multiple) @select_options(${this.var}, ${data}.value);
`);
}
} }
} }

@ -223,16 +223,17 @@ export default class InlineComponentWrapper extends Wrapper {
const all_dependencies: Set<string> = new Set(); const all_dependencies: Set<string> = new Set();
this.node.attributes.forEach(attr => { this.node.attributes.forEach(attr => {
add_to_set(all_dependencies, attr.dependencies); add_to_set(all_dependencies, attr.get_dependencies());
}); });
this.node.attributes.forEach((attr, i) => { this.node.attributes.forEach((attr) => {
const { name, dependencies } = attr; const { name } = attr;
const dependencies = attr.get_dependencies();
const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size) const condition = dependencies.length > 0 && (dependencies.length !== all_dependencies.size)
? renderer.dirty(Array.from(dependencies)) ? renderer.dirty(Array.from(dependencies))
: null; : null;
const unchanged = dependencies.size === 0; const unchanged = dependencies.length === 0;
let change_object; let change_object;
if (attr.is_spread) { if (attr.is_spread) {

@ -0,0 +1,47 @@
export default {
props: {
props: {
foo: 'lol',
baz: 40 + 2,
}
},
html: `
<div baz="42" foo="lol" qux="named"></div>
`,
test({ assert, component, target }) {
const html = `
<div qux="named"></div>
`;
// test undefined
component.props = undefined;
assert.htmlEqual(target.innerHTML, html);
// set object props
component.props = this.props.props;
assert.htmlEqual(target.innerHTML, this.html);
// test null
component.props = null;
assert.htmlEqual(target.innerHTML, html);
// set object props
component.props = this.props.props;
assert.htmlEqual(target.innerHTML, this.html);
// test boolean
component.props = true;
assert.htmlEqual(target.innerHTML, html);
// set object props
component.props = this.props.props;
assert.htmlEqual(target.innerHTML, this.html);
// test number
component.props = 123;
assert.htmlEqual(target.innerHTML, html);
}
};

@ -0,0 +1,5 @@
<script>
export let props;
</script>
<div {...props} qux="named"/>
Loading…
Cancel
Save