From f648bb6548bd3878234d3e62782d0574653dea9a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 2 Dec 2018 16:42:14 -0500 Subject: [PATCH] skip definition if unnecessary --- src/compile/Component.ts | 6 ++- src/compile/nodes/shared/Expression.ts | 4 +- src/compile/render-dom/index.ts | 49 +++++++++++++------ .../render-dom/wrappers/Element/index.ts | 10 +--- .../wrappers/InlineComponent/index.ts | 2 + src/compile/render-dom/wrappers/Window.ts | 2 + .../samples/ssr-no-oncreate-etc/expected.js | 3 +- 7 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/compile/Component.ts b/src/compile/Component.ts index a47063242b..36c3d3faa3 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -51,6 +51,7 @@ export default class Component { ast: Ast; source: string; + code: MagicString; name: string; options: CompileOptions; fragment: Fragment; @@ -77,8 +78,7 @@ export default class Component { module_exports: Array<{ name: string, as: string }> = []; partly_hoisted: string[] = []; fully_hoisted: string[] = []; - - code: MagicString; + has_reactive_assignments = false; indirectDependencies: Map> = new Map(); template_references: Set = new Set(); @@ -663,6 +663,8 @@ export default class Component { else { this.code.appendLeft(node.end, `; $$make_dirty('${name}')`); } + + this.has_reactive_assignments = true; } } diff --git a/src/compile/nodes/shared/Expression.ts b/src/compile/nodes/shared/Expression.ts index 80bc89a678..a067e0cac6 100644 --- a/src/compile/nodes/shared/Expression.ts +++ b/src/compile/nodes/shared/Expression.ts @@ -239,8 +239,6 @@ export default class Expression { // TODO handle destructuring assignments const { name } = flattenReference(node.left); pending_assignments.add(name); - - // code.appendLeft(node.end, `; $$make_dirty('${name}')`); } } else { if (node.type === 'AssignmentExpression') { @@ -290,6 +288,8 @@ export default class Expression { const insert = [...pending_assignments].map(name => `$$make_dirty('${name}');`); pending_assignments = new Set(); + component.has_reactive_assignments = true; + body = deindent` { const $$result = ${body}; diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts index 2b266b21b7..c07806c7d4 100644 --- a/src/compile/render-dom/index.ts +++ b/src/compile/render-dom/index.ts @@ -168,6 +168,10 @@ export default function dom( }); } + const args = ['$$self']; + if (component.props.length > 0 || component.has_reactive_assignments) args.push('$$props'); + if (component.has_reactive_assignments) args.push('$$make_dirty'); + builder.addBlock(deindent` function create_fragment(${component.alias('component')}, ctx) { ${block.getContents()} @@ -176,22 +180,37 @@ export default function dom( ${component.module_javascript} ${component.fully_hoisted.length > 0 && component.fully_hoisted.join('\n\n')} + `); - function ${component.alias('define')}($$self, $$props, $$make_dirty) { - ${component.javascript || ( - component.props.length > 0 && - `let { ${component.props.map(x => x.name === x.as ? x.as : `${x.as}: ${x.name}`).join(', ')} } = $$props;` - )} + let has_definition = ( + component.javascript || + component.props.length > 0 || + component.partly_hoisted.length > 0 || + component.declarations.length > 0 + ); - ${component.partly_hoisted.length > 0 && component.partly_hoisted.join('\n\n')} + const definition = has_definition + ? component.alias('define') + : '@noop'; - $$self.$$.get = () => ({ ${component.declarations.join(', ')} }); + if (has_definition) { + builder.addBlock(deindent` + function ${definition}(${args.join(', ')}) { + ${component.javascript || ( + component.props.length > 0 && + `let { ${component.props.map(x => x.name === x.as ? x.as : `${x.as}: ${x.name}`).join(', ')} } = $$props;` + )} - ${set && `$$self.$$.set = ${set};`} + ${component.partly_hoisted.length > 0 && component.partly_hoisted.join('\n\n')} - ${inject_refs && `$$self.$$.inject_refs = ${inject_refs};`} - } - `); + $$self.$$.get = () => ({ ${component.declarations.join(', ')} }); + + ${set && `$$self.$$.set = ${set};`} + + ${inject_refs && `$$self.$$.inject_refs = ${inject_refs};`} + } + `); + } if (options.customElement) { builder.addBlock(deindent` @@ -201,7 +220,7 @@ export default function dom( ${css.code && `this.shadowRoot.innerHTML = \`\`;`} - @init(this, { target: this.shadowRoot }, ${component.alias('define')}, create_fragment, ${not_equal}); + @init(this, { target: this.shadowRoot }, ${definition}, create_fragment, ${not_equal}); ${dev_props_check} @@ -221,7 +240,7 @@ export default function dom( return ${JSON.stringify(component.props.map(x => x.as))}; } - ${body.join('\n\n')} + ${body.length > 0 && body.join('\n\n')} } customElements.define("${component.tag}", ${name}); @@ -232,12 +251,12 @@ export default function dom( constructor(options) { super(${options.dev && `options`}); ${should_add_css && `if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`} - @init(this, options, define, create_fragment, ${not_equal}); + @init(this, options, ${definition}, create_fragment, ${not_equal}); ${dev_props_check} } - ${body.join('\n\n')} + ${body.length > 0 && body.join('\n\n')} } `); } diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index c25b7e7e9f..eec46534cd 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -389,9 +389,7 @@ export default class ElementWrapper extends Wrapper { if (this.bindings.length === 0) return; - if (this.node.name === 'select' || this.isMediaNode()) { - this.renderer.hasComplexBindings = true; - } + renderer.component.has_reactive_assignments = true; const needsLock = this.node.name !== 'input' || !/radio|checkbox|range|color/.test(this.getStaticAttributeValue('type')); @@ -415,7 +413,7 @@ export default class ElementWrapper extends Wrapper { groups.forEach(group => { const handler = block.getUniqueName(`${this.var}_${group.events.join('_')}_handler`); - this.renderer.component.declarations.push(handler); + renderer.component.declarations.push(handler); const needsLock = group.bindings.some(binding => binding.needsLock); @@ -521,16 +519,12 @@ export default class ElementWrapper extends Wrapper { .join(' || '); if (this.node.name === 'select' || group.bindings.find(binding => binding.name === 'indeterminate' || binding.isReadOnlyMediaAttribute)) { - renderer.hasComplexBindings = true; - block.builders.hydrate.addLine( `if (${someInitialStateIsUndefined}) @add_render_callback(() => ${callee}.call(${this.var}));` ); } if (group.events[0] === 'resize') { - renderer.hasComplexBindings = true; - block.builders.hydrate.addLine( `@add_render_callback(() => ${callee}.call(${this.var}));` ); diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index c74ad0a571..9506426cb8 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -193,6 +193,8 @@ export default class InlineComponentWrapper extends Wrapper { } const munged_bindings = this.node.bindings.map(binding => { + component.has_reactive_assignments = true; + const name = component.getUniqueName(`${this.var}_${binding.name}_binding`); component.declarations.push(name); diff --git a/src/compile/render-dom/wrappers/Window.ts b/src/compile/render-dom/wrappers/Window.ts index 154697b6d1..a7e367d1c4 100644 --- a/src/compile/render-dom/wrappers/Window.ts +++ b/src/compile/render-dom/wrappers/Window.ts @@ -125,6 +125,8 @@ export default class WindowWrapper extends Wrapper { block.builders.destroy.addBlock(deindent` window.removeEventListener("${event}", ctx.${handler_name}); `); + + component.has_reactive_assignments = true; }); // special case... might need to abstract this out if we add more special cases diff --git a/test/js/samples/ssr-no-oncreate-etc/expected.js b/test/js/samples/ssr-no-oncreate-etc/expected.js index e090cd2f10..50e3e6ed23 100644 --- a/test/js/samples/ssr-no-oncreate-etc/expected.js +++ b/test/js/samples/ssr-no-oncreate-etc/expected.js @@ -63,4 +63,5 @@ SvelteComponent.css = { }; var warned = false; -export default SvelteComponent; \ No newline at end of file +export default SvelteComponent; +export { preload }; \ No newline at end of file