From aaf7acce77359c159569b0d8e456dbee56094d22 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 23 Nov 2018 16:29:15 -0500 Subject: [PATCH] use hoisting mechanism for components --- .../render-dom/wrappers/Element/index.ts | 74 +++++++------------ .../wrappers/InlineComponent/index.ts | 36 +-------- 2 files changed, 26 insertions(+), 84 deletions(-) diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index 38257aba0f..10e08bc94d 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -633,62 +633,38 @@ export default class ElementWrapper extends Wrapper { const { component } = renderer; this.node.handlers.forEach(handler => { - const { isCustomEvent } = handler; + const modifiers = []; + if (handler.modifiers.has('preventDefault')) modifiers.push('event.preventDefault();'); + if (handler.modifiers.has('stopPropagation')) modifiers.push('event.stopPropagation();'); - // get a name for the event handler that is globally unique - const handler_name = component.getUniqueName( - `${handler.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler` - ); - - const component_name = block.alias('component'); // can't use #component, might be hoisted + const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod)); + if (opts.length) { + const optString = (opts.length === 1 && opts[0] === 'capture') + ? 'true' + : `{ ${opts.map(opt => `${opt}: true`).join(', ')} }`; - if (isCustomEvent) { - throw new Error(`TODO figure out custom events`); - block.addVariable(handler_name); - - block.builders.hydrate.addBlock(deindent` - ${handler_name} = ctx.${handler.name}.call(${component_name}, ${this.var}, function(event) { - ${handler.snippet} - }); - `); + block.builders.hydrate.addLine( + `@addListener(${this.var}, "${handler.name}", ${handler.snippet}, ${optString});` + ); - block.builders.destroy.addLine(deindent` - ${handler_name}.destroy(); - `); + block.builders.destroy.addLine( + `@removeListener(${this.var}, "${handler.name}", ${handler.snippet}, ${optString});` + ); } else { - const modifiers = []; - if (handler.modifiers.has('preventDefault')) modifiers.push('event.preventDefault();'); - if (handler.modifiers.has('stopPropagation')) modifiers.push('event.stopPropagation();'); - - let name = handler.expression.snippet; - - const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod)); - if (opts.length) { - const optString = (opts.length === 1 && opts[0] === 'capture') - ? 'true' - : `{ ${opts.map(opt => `${opt}: true`).join(', ')} }`; - - block.builders.hydrate.addLine( - `@addListener(${this.var}, "${handler.name}", ${name}, ${optString});` - ); - - block.builders.destroy.addLine( - `@removeListener(${this.var}, "${handler.name}", ${name}, ${optString});` - ); - } else { - block.builders.hydrate.addLine( - `@addListener(${this.var}, "${handler.name}", ${name});` - ); + block.builders.hydrate.addLine( + `@addListener(${this.var}, "${handler.name}", ${handler.snippet});` + ); - block.builders.destroy.addLine( - `@removeListener(${this.var}, "${handler.name}", ${name});` - ); - } + block.builders.destroy.addLine( + `@removeListener(${this.var}, "${handler.name}", ${handler.snippet});` + ); } - handler.expression.declarations.forEach(declaration => { - block.builders.init.addBlock(declaration); - }); + if (handler.expression) { + handler.expression.declarations.forEach(declaration => { + block.builders.init.addBlock(declaration); + }); + } }); } diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index b56a23a32e..abbf3143b9 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -256,41 +256,7 @@ export default class InlineComponentWrapper extends Wrapper { } const munged_handlers = this.node.handlers.map(handler => { - let { snippet } = handler; - - // get a name for the event handler that is globally unique - const handler_name = component.getUniqueName( - `${handler.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler` - ); - component.declarations.push(handler_name); - - if (handler.expression && handler.expression.contextual_dependencies.size > 0) { - block.maintainContext = true; // TODO is there a better place to put this? - - const deps = Array.from(handler.expression.contextual_dependencies); - - component.partly_hoisted.push(deindent` - function ${handler_name}(event, { ${deps.join(', ')} }) { - (${snippet})(event); - } - `); - - block.builders.init.addBlock(deindent` - function ${handler.name}(event) { - ctx.${handler_name}.call(this, event, ctx); - } - `); - - return `${name}.$on("${handler.name}", ${handler_name})`; - } - - component.partly_hoisted.push(deindent` - function ${handler_name}(event) { - (${snippet})(event); - } - `); - - return `${name}.$on("${handler.name}", ctx.${handler_name})`; + return `${name}.$on("${handler.name}", ${handler.snippet})`; }); if (this.node.name === 'svelte:component') {