From ab8ca084315afb8239751d193fb6464f0e31fa5b Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sun, 17 Nov 2019 21:18:40 -0500 Subject: [PATCH] slots --- src/compiler/compile/render_dom/Renderer.ts | 13 ++++++++++ src/compiler/compile/render_dom/index.ts | 26 ++++++------------- .../wrappers/Element/EventHandler.ts | 21 ++++++--------- .../wrappers/InlineComponent/index.ts | 2 +- .../compile/render_dom/wrappers/Slot.ts | 24 ++++++++--------- src/runtime/internal/Component.ts | 6 ++--- src/runtime/internal/utils.ts | 16 ++++++------ 7 files changed, 53 insertions(+), 55 deletions(-) diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index 40c2d9234e..98e846478c 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -34,6 +34,19 @@ export default class Renderer { .filter(v => ((v.referenced || v.export_name) && !v.hoistable)) .forEach(v => this.add_to_context(v.name)); + if (component.var_lookup.has('$$props')) { + this.add_to_context('$$props'); + } + + if (component.slots.size > 0) { + this.add_to_context('$$slots'); + this.add_to_context('$$scope'); + } + + if (this.binding_groups.length > 0) { + this.add_to_context('$$binding_groups'); + } + // main block this.block = new Block({ renderer: this, diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 18f21e276a..b4f716a9b2 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -257,14 +257,6 @@ export default function dom( ${component.fully_hoisted} `); - const filtered_declarations = renderer.context - .map(name => name ? ({ - type: 'Identifier', - name - }) as Expression : x`null`); - - if (uses_props) filtered_declarations.push(x`$$props = @exclude_internal_props($$props)`); - const filtered_props = props.filter(prop => { const variable = component.var_lookup.get(prop.name); @@ -275,14 +267,6 @@ export default function dom( const reactive_stores = component.vars.filter(variable => variable.name[0] === '$' && variable.name[1] !== '$'); - if (component.slots.size > 0) { - filtered_declarations.push(x`$$slots`, x`$$scope`); - } - - if (renderer.binding_groups.length > 0) { - filtered_declarations.push(x`$$binding_groups`); - } - const instance_javascript = component.extract_javascript(component.ast.instance); const has_definition = ( @@ -290,7 +274,7 @@ export default function dom( filtered_props.length > 0 || uses_props || component.partly_hoisted.length > 0 || - filtered_declarations.length > 0 || + renderer.context.length > 0 || component.reactive_declarations.length > 0 ); @@ -379,7 +363,11 @@ export default function dom( const return_value = { type: 'ArrayExpression', - elements: filtered_declarations + elements: renderer.context + .map(name => name ? ({ + type: 'Identifier', + name + }) as Expression : x`null`) }; const reactive_dependencies = { @@ -428,6 +416,8 @@ export default function dom( ${fixed_reactive_declarations} + ${uses_props && b`$$props = @exclude_internal_props($$props);`} + return ${return_value}; } `); diff --git a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts index d76b4ce54d..e247156f8b 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts @@ -15,12 +15,7 @@ export default class EventHandlerWrapper { this.parent = parent; if (!node.expression) { - // TODO use renderer.add_to_context - this.parent.renderer.component.add_var({ - name: node.handler_name.name, - internal: true, - referenced: true, - }); + this.parent.renderer.add_to_context(node.handler_name.name); this.parent.renderer.component.partly_hoisted.push(b` function ${node.handler_name.name}(event) { @@ -30,26 +25,26 @@ export default class EventHandlerWrapper { } } - get_snippet(block) { - const snippet = this.node.expression ? this.node.expression.manipulate(block) : x`#ctx.${this.node.handler_name}`; + get_snippet(block) { + const snippet = this.node.expression ? this.node.expression.manipulate(block) : block.renderer.reference(this.node.handler_name.name); if (this.node.reassigned) { block.maintain_context = true; return x`function () { ${snippet}.apply(this, arguments); }`; } return snippet; - } + } render(block: Block, target: string) { let snippet = this.get_snippet(block); - if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`; + if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`; if (this.node.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`; if (this.node.modifiers.has('self')) snippet = x`@self(${snippet})`; - const args = []; + const args = []; - const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod)); + const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod)); if (opts.length) { args.push((opts.length === 1 && opts[0] === 'capture') ? TRUE @@ -63,7 +58,7 @@ export default class EventHandlerWrapper { args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE); } - block.event_listeners.push( + block.event_listeners.push( x`@listen(${target}, "${this.node.name}", ${snippet}, ${args})` ); } diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index bc6d32c524..69cb0f8d5a 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -354,7 +354,7 @@ export default class InlineComponentWrapper extends Wrapper { component.partly_hoisted.push(body); - return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`; + return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${renderer.context_lookup.get(binding.name)}, ${id}));`; }); const munged_handlers = this.node.handlers.map(handler => { diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 9568010732..761652b173 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -59,12 +59,12 @@ export default class SlotWrapper extends Wrapper { const { slot_name } = this.node; - let get_slot_changes; - let get_slot_context; + let get_slot_changes_fn; + let get_slot_context_fn; if (this.node.values.size > 0) { - get_slot_changes = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`); - get_slot_context = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`); + get_slot_changes_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_changes`); + get_slot_context_fn = renderer.component.get_unique_name(`get_${sanitize(slot_name)}_slot_context`); const context = get_slot_data(this.node.values); const changes = x`{}` as ObjectExpression; @@ -105,20 +105,20 @@ export default class SlotWrapper extends Wrapper { }; renderer.blocks.push(b` - const ${get_slot_changes} = (${arg}) => (${changes}); - const ${get_slot_context} = (${arg}) => (${context}); + const ${get_slot_changes_fn} = (${arg}) => (${changes}); + const ${get_slot_context_fn} = (${arg}) => (${context}); `); } else { - get_slot_changes = 'null'; - get_slot_context = 'null'; + get_slot_changes_fn = 'null'; + get_slot_context_fn = 'null'; } const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`); const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`); block.chunks.init.push(b` - const ${slot_definition} = #ctx.$$slots.${slot_name}; - const ${slot} = @create_slot(${slot_definition}, #ctx, ${get_slot_context}); + const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name}; + const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}); `); // TODO this is a dreadful hack! Should probably make this nicer @@ -185,8 +185,8 @@ export default class SlotWrapper extends Wrapper { block.chunks.update.push(b` if (${slot} && ${slot}.p && ${renderer.changed(dynamic_dependencies)}) { ${slot}.p( - @get_slot_context(${slot_definition}, #ctx, ${get_slot_context}), - @get_slot_changes(${slot_definition}, #ctx, #changed, ${get_slot_changes}) + @get_slot_context(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}), + @get_slot_changes(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, #changed, ${get_slot_changes_fn}) ); } `); diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index b035d958ed..6d8f49957e 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -36,11 +36,11 @@ interface T$$ { on_destroy: any[]; } -export function bind(component, name, callback) { +export function bind(component, name, index, callback) { if (has_prop(component.$$.props, name)) { name = component.$$.props[name] || name; - component.$$.bound[name] = callback; - callback(component.$$.ctx[name]); + component.$$.bound[index] = callback; + callback(component.$$.ctx[index]); } } diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index 6816f8684a..22b58adc94 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -63,23 +63,23 @@ export function component_subscribe(component, store, callback) { component.$$.on_destroy.push(subscribe(store, callback)); } -export function create_slot(definition, ctx, fn) { +export function create_slot(definition, ctx, $$scope, fn) { if (definition) { - const slot_ctx = get_slot_context(definition, ctx, fn); + const slot_ctx = get_slot_context(definition, ctx, $$scope, fn); return definition[0](slot_ctx); } } -export function get_slot_context(definition, ctx, fn) { +export function get_slot_context(definition, ctx, $$scope, fn) { return definition[1] - ? assign({}, assign(ctx.$$scope.ctx, definition[1](fn ? fn(ctx) : {}))) - : ctx.$$scope.ctx; + ? assign({}, assign($$scope.ctx, definition[1](fn ? fn(ctx) : {}))) + : $$scope.ctx; } -export function get_slot_changes(definition, ctx, changed, fn) { +export function get_slot_changes(definition, ctx, $$scope, changed, fn) { return definition[1] - ? assign({}, assign(ctx.$$scope.changed || {}, definition[1](fn ? fn(changed) : {}))) - : ctx.$$scope.changed || {}; + ? assign({}, assign($$scope.changed || {}, definition[1](fn ? fn(changed) : {}))) + : $$scope.changed || {}; } export function exclude_internal_props(props) {