some component binding stuff

pull/1864/head
Rich Harris 7 years ago
parent cc2c78677a
commit 358d852ce0

@ -22,7 +22,6 @@ export default class Renderer {
hasIntroTransitions: boolean; hasIntroTransitions: boolean;
hasOutroTransitions: boolean; hasOutroTransitions: boolean;
hasComplexBindings: boolean;
constructor(component: Component, options: CompileOptions) { constructor(component: Component, options: CompileOptions) {
this.component = component; this.component = component;

@ -99,7 +99,6 @@ export default class InlineComponentWrapper extends Wrapper {
const name_initial_data = block.getUniqueName(`${name}_initial_data`); const name_initial_data = block.getUniqueName(`${name}_initial_data`);
const name_changes = block.getUniqueName(`${name}_changes`); const name_changes = block.getUniqueName(`${name}_changes`);
let name_updating: string; let name_updating: string;
let beforecreate: string = null;
const updates: string[] = []; const updates: string[] = [];
@ -186,9 +185,39 @@ export default class InlineComponentWrapper extends Wrapper {
} }
} }
if (this.node.bindings.length) { const munged_bindings = this.node.bindings.map(binding => {
renderer.hasComplexBindings = true; const name = component.getUniqueName(`${this.var}_${binding.name}_binding`);
const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
const dependencies = Array.from(binding.expression.dependencies);
const lhs = component.source.slice(binding.expression.node.start, binding.expression.node.end).trim();
const args = ['value'];
if (contextual_dependencies.length > 0) {
args.push(`{ ${contextual_dependencies.join(', ')} }`);
block.builders.init.addBlock(deindent`
function ${name}(value) {
ctx.${name}.call(null, value, ctx);
}
`);
}
const body = deindent`
function ${name}(${args.join(', ')}) {
${lhs} = value;
${dependencies.map(dep => `$$make_dirty('${dep}');`)}
}
`;
component.event_handlers.push({ name, body });
return contextual_dependencies.length > 0
? `${this.var}.$$bind('${binding.name}', ${name});`
: `${this.var}.$$bind('${binding.name}', ctx.${name});`;
});
if (this.node.bindings.length) {
name_updating = block.alias(`${name}_updating`); name_updating = block.alias(`${name}_updating`);
block.addVariable(name_updating, '{}'); block.addVariable(name_updating, '{}');
@ -238,7 +267,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (${switch_value}) { if (${switch_value}) {
var ${name} = new ${switch_value}(${switch_props}(ctx)); var ${name} = new ${switch_value}(${switch_props}(ctx));
${beforecreate} ${munged_bindings}
} }
${this.node.handlers.map(handler => deindent` ${this.node.handlers.map(handler => deindent`
@ -292,13 +321,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (${switch_value}) { if (${switch_value}) {
${name} = new ${switch_value}(${switch_props}(ctx)); ${name} = new ${switch_value}(${switch_props}(ctx));
${this.node.bindings.length > 0 && deindent` ${munged_bindings}
#component.$$root._beforecreate.push(() => {
const changed = {};
${this.node.bindings.map(binding => deindent`
if (${binding.expression.snippet} === void 0) changed.${binding.name} = 1;`)}
${name}._bind(changed, ${name}.get());
});`}
${name}.$$fragment.c(); ${name}.$$fragment.c();
${this.fragment && this.fragment.nodes.map(child => child.remount(name))} ${this.fragment && this.fragment.nodes.map(child => child.remount(name))}
@ -342,7 +365,7 @@ export default class InlineComponentWrapper extends Wrapper {
${componentInitProperties.join(',\n')} ${componentInitProperties.join(',\n')}
}); });
${beforecreate} ${munged_bindings}
${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`} ${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`}
`); `);
@ -413,31 +436,6 @@ export default class InlineComponentWrapper extends Wrapper {
`); `);
} }
this.node.bindings.forEach(binding => {
const binding_name = component.getUniqueName(`${this.var}_${binding.name}_binding`);
if (binding.expression.contextual_dependencies.size > 0) {
throw new Error(`TODO bindings with contextual dependencies`);
} else {
const lhs = component.source.slice(binding.expression.node.start, binding.expression.node.end);
const deps = Array.from(binding.expression.dependencies);
component.event_handlers.push({
name: binding_name,
body: deindent`
function ${binding_name}(value) {
${lhs} = value;
${deps.map(dep => `$$make_dirty('${dep}');`)}
}
`
});
block.builders.init.addBlock(deindent`
${this.var}.$$bind('${binding.name}', ctx.${binding_name});
`);
}
});
if (component.options.nestedTransitions) { if (component.options.nestedTransitions) {
block.builders.outro.addLine( block.builders.outro.addLine(
`if (${name}) ${name}.$$fragment.o(#outrocallback);` `if (${name}) ${name}.$$fragment.o(#outrocallback);`

@ -60,7 +60,7 @@ export class SvelteComponent {
$set(values) { $set(values) {
if (this.$$) { if (this.$$) {
this.$$.inject_props(values); this.$$.inject_props(values);
run_all(this.$$onprops); run_all(this.$$onprops); // TODO should this be deferred until the update?
for (const key in values) this.$$make_dirty(key); for (const key in values) this.$$make_dirty(key);
} }

@ -9,7 +9,7 @@ export function schedule_update(component) {
dirty_components.push(component); dirty_components.push(component);
if (!update_scheduled) { if (!update_scheduled) {
update_scheduled = true; update_scheduled = true;
queueMicrotask(flush); queue_microtask(flush);
} }
} }
@ -29,6 +29,6 @@ export function flush() {
update_scheduled = false; update_scheduled = false;
} }
function queueMicrotask(callback) { function queue_microtask(callback) {
Promise.resolve().then(callback); Promise.resolve().then(callback);
} }

@ -8,10 +8,10 @@ export default {
<input> <input>
`, `,
test(assert, component, target, window) { async test(assert, component, target, window) {
let input = target.querySelector('input'); let input = target.querySelector('input');
input.value = 'abc'; input.value = 'abc';
input.dispatchEvent(new window.Event('input')); await input.dispatchEvent(new window.Event('input'));
assert.equal(component.y, 'abc'); assert.equal(component.y, 'abc');
@ -24,7 +24,7 @@ export default {
input = target.querySelector('input'); input = target.querySelector('input');
input.checked = true; input.checked = true;
input.dispatchEvent(new window.Event('change')); await input.dispatchEvent(new window.Event('change'));
assert.equal(component.z, true); assert.equal(component.z, true);
} }

@ -1,5 +1,6 @@
<script> <script>
export let foo; export let foo;
export let x;
</script> </script>
{#if x} {#if x}

Loading…
Cancel
Save