use hoisting mechanism for components

pull/1864/head
Rich Harris 7 years ago
parent 85a4b5272a
commit aaf7acce77

@ -633,62 +633,38 @@ export default class ElementWrapper extends Wrapper {
const { component } = renderer; const { component } = renderer;
this.node.handlers.forEach(handler => { 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 opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod));
const handler_name = component.getUniqueName( if (opts.length) {
`${handler.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler` const optString = (opts.length === 1 && opts[0] === 'capture')
); ? 'true'
: `{ ${opts.map(opt => `${opt}: true`).join(', ')} }`;
const component_name = block.alias('component'); // can't use #component, might be hoisted
if (isCustomEvent) { block.builders.hydrate.addLine(
throw new Error(`TODO figure out custom events`); `@addListener(${this.var}, "${handler.name}", ${handler.snippet}, ${optString});`
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.destroy.addLine(deindent` block.builders.destroy.addLine(
${handler_name}.destroy(); `@removeListener(${this.var}, "${handler.name}", ${handler.snippet}, ${optString});`
`); );
} else { } else {
const modifiers = []; block.builders.hydrate.addLine(
if (handler.modifiers.has('preventDefault')) modifiers.push('event.preventDefault();'); `@addListener(${this.var}, "${handler.name}", ${handler.snippet});`
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.destroy.addLine( block.builders.destroy.addLine(
`@removeListener(${this.var}, "${handler.name}", ${name});` `@removeListener(${this.var}, "${handler.name}", ${handler.snippet});`
); );
}
} }
handler.expression.declarations.forEach(declaration => { if (handler.expression) {
block.builders.init.addBlock(declaration); handler.expression.declarations.forEach(declaration => {
}); block.builders.init.addBlock(declaration);
});
}
}); });
} }

@ -256,41 +256,7 @@ export default class InlineComponentWrapper extends Wrapper {
} }
const munged_handlers = this.node.handlers.map(handler => { const munged_handlers = this.node.handlers.map(handler => {
let { snippet } = handler; return `${name}.$on("${handler.name}", ${handler.snippet})`;
// 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})`;
}); });
if (this.node.name === 'svelte:component') { if (this.node.name === 'svelte:component') {

Loading…
Cancel
Save