From 1d8d17bc0714b7aa97df293631826b3aae717b02 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Wed, 11 Sep 2019 08:51:37 -0400 Subject: [PATCH] hoist nodes, not snippets --- package-lock.json | 6 +++--- package.json | 2 +- src/compiler/compile/Component.ts | 20 +++++++++++++------ src/compiler/compile/nodes/EventHandler.ts | 4 ++-- .../compile/nodes/shared/Expression.ts | 6 ++++-- src/compiler/compile/render_dom/index.ts | 3 ++- .../compile/render_dom/wrappers/Text.ts | 5 ++--- src/compiler/compile/render_ssr/index.ts | 2 +- .../compile/utils/flatten_reference.ts | 4 +--- src/compiler/compile/utils/snip.ts | 1 + test/runtime/samples/_/main.svelte | 6 +++++- 11 files changed, 36 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7479160cad..ada0a223f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -507,9 +507,9 @@ "dev": true }, "code-red": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/code-red/-/code-red-0.0.7.tgz", - "integrity": "sha512-UgcXT2tiYOFe5MF6FYeP1s+XKvd5XFlm+p+By6/Q/0/NwgT2ZqkR32liLhosDivtO1vvtLTg51LN1LUW5AYSEw==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-0.0.8.tgz", + "integrity": "sha512-wvKPondTM1H6MoUnz5tj6z1xawzmaulkC0qLv5S1KLkShWgRybgIdvGyVr5pPQt2ovpdmh6BcpRXXoqs5X8tcA==", "dev": true, "requires": { "acorn": "^7.0.0", diff --git a/package.json b/package.json index 42eb37276f..f7d3d85a4e 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "acorn": "^7.0.0", "agadoo": "^1.0.1", "c8": "^5.0.1", - "code-red": "0.0.7", + "code-red": "0.0.8", "codecov": "^3.5.0", "css-tree": "1.0.0-alpha22", "eslint": "^6.3.0", diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index c915251e4d..2edc2d6cfc 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -111,8 +111,8 @@ export default class Component { hoistable_nodes: Set = new Set(); node_for_declaration: Map = new Map(); - partly_hoisted: string[] = []; - fully_hoisted: string[] = []; + partly_hoisted: Node[] = []; + fully_hoisted: Node[] = []; reactive_declarations: Array<{ assignees: Set; dependencies: Set; @@ -1077,7 +1077,11 @@ export default class Component { const top_level_function_declarations = new Map(); - this.ast.instance.content.body.forEach(node => { + const { body } = this.ast.instance.content; + let i = body.length; + while (i--) { + const node = body[i]; + if (node.type === 'VariableDeclaration') { const all_hoistable = node.declarations.every(d => { if (!d.init) return false; @@ -1105,7 +1109,9 @@ export default class Component { }); hoistable_nodes.add(node); - this.fully_hoisted.push(`[✂${node.start}-${node.end}✂]`); + + body.splice(i, 1); + this.fully_hoisted.push(node); } } @@ -1120,7 +1126,7 @@ export default class Component { if (node.type === 'FunctionDeclaration') { top_level_function_declarations.set(node.id.name, node); } - }); + } const checked = new Set(); const walking = new Set(); @@ -1209,7 +1215,9 @@ export default class Component { remove_indentation(this.code, node); - this.fully_hoisted.push(`[✂${node.start}-${node.end}✂]`); + const i = body.indexOf(node); + body.splice(i, 1); + this.fully_hoisted.push(node); } } } diff --git a/src/compiler/compile/nodes/EventHandler.ts b/src/compiler/compile/nodes/EventHandler.ts index 428ee678bf..688f7e85ce 100644 --- a/src/compiler/compile/nodes/EventHandler.ts +++ b/src/compiler/compile/nodes/EventHandler.ts @@ -1,7 +1,7 @@ import Node from './shared/Node'; import Expression from './shared/Expression'; import Component from '../Component'; -import deindent from '../utils/deindent'; +import { b } from 'code-red'; import Block from '../render_dom/Block'; import { sanitize } from '../../utils/names'; import { Identifier } from '../../interfaces'; @@ -51,7 +51,7 @@ export default class EventHandler extends Node { referenced: true }); - component.partly_hoisted.push(deindent` + component.partly_hoisted.push(b` function ${id}(event) { @bubble($$self, event); } diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index ffb0f4ea3a..87469309f9 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -325,8 +325,8 @@ export default class Expression { const body = code.slice(node.body.start, node.body.end).trim(); const fn = node.type === 'FunctionExpression' - ? `${node.async ? 'async ' : ''}function${node.generator ? '*' : ''} ${id}(${args.join(', ')}) ${body}` - : `const ${id} = ${node.async ? 'async ' : ''}(${args.join(', ')}) => ${body};`; + ? b`${node.async ? 'async ' : ''}function${node.generator ? '*' : ''} ${id}(${args.join(', ')}) ${body}` + : b`const ${id} = ${node.async ? 'async ' : ''}(${args.join(', ')}) => ${body};`; if (dependencies.size === 0 && contextual_dependencies.size === 0) { // we can hoist this out of the component completely @@ -411,6 +411,8 @@ export default class Expression { }); } + throw new Error(`bad`); + return this.rendered = `[✂${this.node.start}-${this.node.end}✂]`; } } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 6612895a25..f514692bed 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -236,7 +236,7 @@ export default function dom( ${component.module_javascript} - ${component.fully_hoisted.length > 0 && component.fully_hoisted.join('\n\n')} + ${component.fully_hoisted} `); const filtered_declarations = component.vars @@ -314,6 +314,7 @@ export default function dom( }) .map(n => `$$dirty.${n}`).join(' || '); + throw new Error(`bad`); let snippet = `[✂${d.node.body.start}-${d.node.end}✂]`; if (condition) snippet = `if (${condition}) { ${snippet} }`; diff --git a/src/compiler/compile/render_dom/wrappers/Text.ts b/src/compiler/compile/render_dom/wrappers/Text.ts index 1ada6805d4..553ecd8e83 100644 --- a/src/compiler/compile/render_dom/wrappers/Text.ts +++ b/src/compiler/compile/render_dom/wrappers/Text.ts @@ -2,7 +2,6 @@ import Renderer from '../Renderer'; import Block from '../Block'; import Text from '../../nodes/Text'; import Wrapper from './shared/Wrapper'; -import { stringify } from '../../utils/stringify'; import { Identifier } from '../../../interfaces'; import { x } from 'code-red'; @@ -72,8 +71,8 @@ export default class TextWrapper extends Wrapper { block.add_element( this.var, - use_space ? x`@space()` : x`@text(${stringify(this.data)})`, - parent_nodes && (use_space ? x`@claim_space(${parent_nodes})` : x`@claim_text(${parent_nodes}, ${stringify(this.data)})`), + use_space ? x`@space()` : x`@text("${this.data}")`, + parent_nodes && (use_space ? x`@claim_space(${parent_nodes})` : x`@claim_text(${parent_nodes}, "${this.data}")`), parent_node ); } diff --git a/src/compiler/compile/render_ssr/index.ts b/src/compiler/compile/render_ssr/index.ts index 29e71f072b..3ab504bd77 100644 --- a/src/compiler/compile/render_ssr/index.ts +++ b/src/compiler/compile/render_ssr/index.ts @@ -145,7 +145,7 @@ export default function ssr( ${component.module_javascript} - ${component.fully_hoisted.length > 0 && component.fully_hoisted.join('\n\n')} + ${component.fully_hoisted} const ${name} = @create_ssr_component(($$result, $$props, $$bindings, $$slots) => { ${blocks.join('\n\n')} diff --git a/src/compiler/compile/utils/flatten_reference.ts b/src/compiler/compile/utils/flatten_reference.ts index 460cd2f1e9..7b814d5e19 100644 --- a/src/compiler/compile/utils/flatten_reference.ts +++ b/src/compiler/compile/utils/flatten_reference.ts @@ -4,7 +4,6 @@ export default function flatten_reference(node: Node) { if (node.type === 'Expression') throw new Error('bad'); const nodes = []; const parts = []; - const prop_end = node.end; while (node.type === 'MemberExpression') { nodes.unshift(node.property); @@ -16,7 +15,6 @@ export default function flatten_reference(node: Node) { node = node.object; } - const prop_start = node.end; const name = node.type === 'Identifier' ? node.name : node.type === 'ThisExpression' ? 'this' : null; @@ -27,5 +25,5 @@ export default function flatten_reference(node: Node) { parts.unshift(name); } - return { name, nodes, parts, keypath: `${name}[✂${prop_start}-${prop_end}✂]` }; + return { name, nodes, parts }; } diff --git a/src/compiler/compile/utils/snip.ts b/src/compiler/compile/utils/snip.ts index 979f1fdc89..7a2e12f8e5 100644 --- a/src/compiler/compile/utils/snip.ts +++ b/src/compiler/compile/utils/snip.ts @@ -1,3 +1,4 @@ export function snip(expression) { + throw new Error(`bad`); return `[✂${expression.node.start}-${expression.node.end}✂]`; } \ No newline at end of file diff --git a/test/runtime/samples/_/main.svelte b/test/runtime/samples/_/main.svelte index efe5048cbc..22b3c84db0 100644 --- a/test/runtime/samples/_/main.svelte +++ b/test/runtime/samples/_/main.svelte @@ -1 +1,5 @@ -

Hello world!

\ No newline at end of file + + +

Hello {name}!

\ No newline at end of file