component bindings etc

pull/3945/head
Rich Harris 6 years ago
parent a74cc6996e
commit 6c3c3bbf2a

@ -332,7 +332,7 @@ export default class Expression {
} }
}); });
this.replace(invalidate(block.renderer, scope, node, traced, false)); this.replace(invalidate(block.renderer, scope, node, traced));
} }
} }
}); });

@ -138,7 +138,7 @@ export default class Renderer {
.reduce((lhs, rhs) => x`${lhs}, ${rhs}}`); .reduce((lhs, rhs) => x`${lhs}, ${rhs}}`);
} }
changed(names, needs_update) { changed(names, needs_update = false) {
const bitmask = names.reduce((bits, name) => { const bitmask = names.reduce((bits, name) => {
const bit = 1 << this.context_lookup.get(name); const bit = 1 << this.context_lookup.get(name);
return bits | bit; return bits | bit;

@ -160,7 +160,7 @@ export default function dom(
const { ctx: #ctx } = this.$$; const { ctx: #ctx } = this.$$;
const props = ${options.customElement ? x`this.attributes` : x`options.props || {}`}; const props = ${options.customElement ? x`this.attributes` : x`options.props || {}`};
${expected.map(prop => b` ${expected.map(prop => b`
if (#ctx.${prop.name} === undefined && !('${prop.export_name}' in props)) { if (${renderer.reference(prop.name)} === undefined && !('${prop.export_name}' in props)) {
@_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'"); @_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
}`)} }`)}
`; `;
@ -405,8 +405,8 @@ export default function dom(
`); `);
} }
const prop_names = x`{ const prop_indexes = x`{
${props.map(v => p`${v.export_name}: ${v.export_name === v.name ? 0 : x`"${v.name}"`}}`)} ${props.map(v => p`${v.export_name}: ${renderer.context_lookup.get(v.name)}`)}
}` as ObjectExpression; }` as ObjectExpression;
if (options.customElement) { if (options.customElement) {
@ -417,7 +417,7 @@ export default function dom(
${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`} ${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
@init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_names}); @init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes});
${dev_props_check} ${dev_props_check}
@ -469,7 +469,7 @@ export default function dom(
constructor(options) { constructor(options) {
super(${options.dev && `options`}); super(${options.dev && `options`});
${should_add_css && b`if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`} ${should_add_css && b`if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
@init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_names}); @init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes});
${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`} ${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
${dev_props_check} ${dev_props_check}

@ -315,24 +315,24 @@ export default class InlineComponentWrapper extends Wrapper {
} }
const value = block.get_unique_name('value'); const value = block.get_unique_name('value');
const args: any[] = [value]; const params: any[] = [value];
if (contextual_dependencies.length > 0) { if (contextual_dependencies.length > 0) {
args.push({ const args = [];
type: 'ObjectPattern',
properties: contextual_dependencies.map(name => { contextual_dependencies.forEach(name => {
const id = { type: 'Identifier', name }; params.push({
return { type: 'Identifier',
type: 'Property', name
kind: 'init', });
key: id,
value: id renderer.add_to_context(name, true);
}; args.push(renderer.reference(name));
})
}); });
block.chunks.init.push(b` block.chunks.init.push(b`
function ${id}(${value}) { function ${id}(${value}) {
#ctx[${i}].call(null, ${value}, #ctx); #ctx[${i}].call(null, ${value}, ${args});
} }
`); `);
@ -346,7 +346,7 @@ export default class InlineComponentWrapper extends Wrapper {
} }
const body = b` const body = b`
function ${id}(${args}) { function ${id}(${params}) {
${lhs} = ${value}; ${lhs} = ${value};
${renderer.invalidate(dependencies[0])}; ${renderer.invalidate(dependencies[0])};
} }
@ -354,7 +354,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.partly_hoisted.push(body); component.partly_hoisted.push(body);
return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${renderer.context_lookup.get(binding.name)}, ${id}));`; return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
}); });
const munged_handlers = this.node.handlers.map(handler => { const munged_handlers = this.node.handlers.map(handler => {

@ -80,6 +80,9 @@ export default class WindowWrapper extends Wrapper {
const id = block.get_unique_name(`onwindow${event}`); const id = block.get_unique_name(`onwindow${event}`);
const props = events[event]; const props = events[event];
renderer.add_to_context(id.name);
const fn = renderer.reference(id.name);
if (event === 'scroll') { if (event === 'scroll') {
// TODO other bidirectional bindings... // TODO other bidirectional bindings...
block.add_variable(scrolling, x`false`); block.add_variable(scrolling, x`false`);
@ -106,7 +109,7 @@ export default class WindowWrapper extends Wrapper {
${scrolling} = true; ${scrolling} = true;
@_clearTimeout(${scrolling_timeout}); @_clearTimeout(${scrolling_timeout});
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100); ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
#ctx.${id}(); ${fn}();
}) })
`); `);
} else { } else {
@ -117,7 +120,7 @@ export default class WindowWrapper extends Wrapper {
}); });
block.event_listeners.push(x` block.event_listeners.push(x`
@listen(@_window, "${event}", #ctx.${id}) @listen(@_window, "${event}", ${fn})
`); `);
} }
@ -139,8 +142,9 @@ export default class WindowWrapper extends Wrapper {
// special case... might need to abstract this out if we add more special cases // special case... might need to abstract this out if we add more special cases
if (bindings.scrollX || bindings.scrollY) { if (bindings.scrollX || bindings.scrollY) {
const condition = renderer.changed([bindings.scrollX, bindings.scrollY].filter(Boolean)); const condition = renderer.changed([bindings.scrollX, bindings.scrollY].filter(Boolean));
const scrollX = bindings.scrollX ? x`#ctx.${bindings.scrollX}` : x`@_window.pageXOffset`;
const scrollY = bindings.scrollY ? x`#ctx.${bindings.scrollY}` : x`@_window.pageYOffset`; const scrollX = bindings.scrollX ? renderer.reference(bindings.scrollX) : x`@_window.pageXOffset`;
const scrollY = bindings.scrollY ? renderer.reference(bindings.scrollY) : x`@_window.pageYOffset`;
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition} && !${scrolling}) { if (${condition} && !${scrolling}) {

@ -53,7 +53,7 @@ export default function bind_this(component: Component, block: Block, binding: B
const args = []; const args = [];
for (const id of contextual_dependencies) { for (const id of contextual_dependencies) {
args.push(id); args.push(id);
block.add_variable(id, x`#ctx.${id}`); block.add_variable(id, block.renderer.reference(id));
} }
const assign = block.get_unique_name(`assign_${variable.name}`); const assign = block.get_unique_name(`assign_${variable.name}`);
@ -65,7 +65,7 @@ export default function bind_this(component: Component, block: Block, binding: B
`); `);
const condition = Array.from(contextual_dependencies) const condition = Array.from(contextual_dependencies)
.map(name => x`${name} !== #ctx.${name}`) // TODO figure out contextual deps .map(name => x`${name} !== ${block.renderer.reference(name)}`) // TODO figure out contextual deps
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`); .reduce((lhs, rhs) => x`${lhs} || ${rhs}`);
// we push unassign and unshift assign so that references are // we push unassign and unshift assign so that references are
@ -74,7 +74,7 @@ export default function bind_this(component: Component, block: Block, binding: B
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition}) { if (${condition}) {
${unassign}(); ${unassign}();
${args.map(a => b`${a} = #ctx.${a}`)}; ${args.map(a => b`${a} = ${block.renderer.reference(a)}`)};
${assign}(); ${assign}();
}` }`
); );

@ -30,7 +30,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
const class_expression_list = node.classes.map(class_directive => { const class_expression_list = node.classes.map(class_directive => {
const { expression, name } = class_directive; const { expression, name } = class_directive;
const snippet = expression ? expression.node : x`#ctx.${name}`; const snippet = expression ? expression.node : x`#ctx.${name}`; // TODO is this right?
return x`${snippet} ? "${name}" : ""`; return x`${snippet} ? "${name}" : ""`;
}); });
if (node.needs_manual_style_scoping) { if (node.needs_manual_style_scoping) {

@ -36,9 +36,9 @@ interface T$$ {
on_destroy: any[]; on_destroy: any[];
} }
export function bind(component, name, index, callback) { export function bind(component, name, callback) {
if (has_prop(component.$$.props, name)) { const index = component.$$.props[name];
name = component.$$.props[name] || name; if (index !== undefined) {
component.$$.bound[index] = callback; component.$$.bound[index] = callback;
callback(component.$$.ctx[index]); callback(component.$$.ctx[index]);
} }

Loading…
Cancel
Save