From 50280232e8e79a5400c7d2415fc6d32b6f96fef0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 11 Sep 2019 18:30:18 -0400 Subject: [PATCH] props --- src/compiler/compile/Component.ts | 257 +++-------- .../compile/nodes/shared/Expression.ts | 413 +++++++++--------- src/compiler/compile/render_dom/index.ts | 4 +- .../compile/render_dom/wrappers/DebugTag.ts | 72 +-- .../compile/render_dom/wrappers/EachBlock.ts | 3 +- .../render_dom/wrappers/MustacheTag.ts | 2 +- .../render_dom/wrappers/RawMustacheTag.ts | 2 +- .../compile/render_dom/wrappers/shared/Tag.ts | 3 +- src/compiler/compile/utils/invalidate.ts | 99 ++--- src/compiler/utils/indentation.ts | 57 --- test/runtime/samples/_/main.svelte | 2 +- 11 files changed, 364 insertions(+), 550 deletions(-) delete mode 100644 src/compiler/utils/indentation.ts diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 2edc2d6cfc..039309cd28 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -1,4 +1,3 @@ -import MagicString from 'magic-string'; // @ts-ignore import { walk, childKeys } from 'estree-walker'; import { getLocator } from 'locate-character'; @@ -23,14 +22,13 @@ import flatten_reference from './utils/flatten_reference'; import is_reference from 'is-reference'; import TemplateScope from './nodes/shared/TemplateScope'; import fuzzymatch from '../utils/fuzzymatch'; -import { remove_indentation, add_indentation } from '../utils/indentation'; import get_object from './utils/get_object'; import unwrap_parens from './utils/unwrap_parens'; import Slot from './nodes/Slot'; import { Node as ESTreeNode } from 'estree'; import add_to_set from './utils/add_to_set'; import check_graph_for_cycles from './utils/check_graph_for_cycles'; -import { print } from 'code-red'; +import { print, x } from 'code-red'; interface ComponentOptions { namespace?: string; @@ -48,37 +46,13 @@ childKeys.Attribute = ['value']; childKeys.ExportNamedDeclaration = ['declaration', 'specifiers']; function remove_node( - code: MagicString, - start: number, - end: number, body: Node, node: Node ) { const i = body.indexOf(node); if (i === -1) throw new Error('node not in list'); - let a; - let b; - - if (body.length === 1) { - // remove everything, leave {} - a = start; - b = end; - } else if (i === 0) { - // remove everything before second node, including comments - a = start; - while (/\s/.test(code.original[a])) a += 1; - - b = body[i].end; - while (/[\s,]/.test(code.original[b])) b += 1; - } else { - // remove the end of the previous node to the end of this one - a = body[i - 1].end; - b = node.end; - } - - code.remove(a, b); - return; + body.splice(i, 1); } export default class Component { @@ -89,7 +63,6 @@ export default class Component { ast: Ast; source: string; - code: MagicString; name: Identifier; compile_options: CompileOptions; fragment: Fragment; @@ -173,8 +146,6 @@ export default class Component { : compile_options.filename); this.locate = getLocator(this.source); - this.code = new MagicString(source); - // styles this.stylesheet = new Stylesheet( source, @@ -261,15 +232,6 @@ export default class Component { } } - add_sourcemap_locations(node: Node) { - walk(node, { - enter: (node: Node) => { - this.code.addSourcemapLocation(node.start); - this.code.addSourcemapLocation(node.end); - }, - }); - } - alias(name: string) { if (!this.aliases.has(name)) { this.aliases.set(name, this.get_unique_name(name)); @@ -502,21 +464,20 @@ export default class Component { } extract_imports(content) { - const { code } = this; - content.body.forEach(node => { if (node.type === 'ImportDeclaration') { // imports need to be hoisted out of the IIFE - remove_node(code, content.start, content.end, content.body, node); + remove_node(content.body, node); this.imports.push(node); } }); } extract_exports(content) { - const { code } = this; + let i = content.body.length; + while (i--) { + const node = content.body[i]; - content.body.forEach(node => { if (node.type === 'ExportDefaultDeclaration') { this.error(node, { code: `default-export`, @@ -546,21 +507,20 @@ export default class Component { variable.export_name = name; } - code.remove(node.start, node.declaration.start); + content.body[i] = node.declaration; } else { - remove_node(code, content.start, content.end, content.body, node); node.specifiers.forEach(specifier => { const variable = this.var_lookup.get(specifier.local.name); if (variable) { variable.export_name = specifier.exported.name; - } else { - // TODO what happens with `export { Math }` or some other global? } }); + + content.body.splice(i, 1); } } - }); + } } extract_javascript(script) { @@ -573,35 +533,37 @@ export default class Component { return true; }); + return nodes_to_include; + if (nodes_to_include.length === 0) return null; let a = script.content.start; while (/\s/.test(this.source[a])) a += 1; - let b = a; + // let b = a; - let result = ''; + // let result = ''; - script.content.body.forEach(node => { - if ( - this.hoistable_nodes.has(node) || - this.reactive_declaration_nodes.has(node) - ) { - if (a !== b) result += `[✂${a}-${b}✂]`; - a = node.end; - } + // script.content.body.forEach(node => { + // if ( + // this.hoistable_nodes.has(node) || + // this.reactive_declaration_nodes.has(node) + // ) { + // if (a !== b) result += `[✂${a}-${b}✂]`; + // a = node.end; + // } - b = node.end; - }); + // b = node.end; + // }); // while (/\s/.test(this.source[a - 1])) a -= 1; - b = script.content.end; - while (/\s/.test(this.source[b - 1])) b -= 1; + // b = script.content.end; + // while (/\s/.test(this.source[b - 1])) b -= 1; - if (a < b) result += `[✂${a}-${b}✂]`; + // if (a < b) result += `[✂${a}-${b}✂]`; - return result || null; + // return result || null; } walk_module_js() { @@ -620,8 +582,6 @@ export default class Component { }, }); - this.add_sourcemap_locations(script.content); - const { scope, globals } = create_scopes(script.content); this.module_scope = scope; @@ -657,7 +617,6 @@ export default class Component { this.extract_imports(script.content); this.extract_exports(script.content); - remove_indentation(this.code, script.content); this.module_javascript = this.extract_javascript(script); } @@ -665,8 +624,6 @@ export default class Component { const script = this.ast.instance; if (!script) return; - this.add_sourcemap_locations(script.content); - // inject vars for reactive declarations script.content.body.forEach(node => { if (node.type !== 'LabeledStatement') return; @@ -893,18 +850,16 @@ export default class Component { .join(', '); } - rewrite_props(get_insert: (variable: Var) => string) { + rewrite_props(_get_insert: (variable: Var) => string) { + // TODO + const component = this; - const { code, instance_scope, instance_scope_map: map } = this; + const { instance_scope, instance_scope_map: map } = this; let scope = instance_scope; - const coalesced_declarations = []; - let current_group; - walk(this.ast.instance.content, { - enter(node, parent) { + enter(node) { if (/Function/.test(node.type)) { - current_group = null; return this.skip(); } @@ -914,16 +869,15 @@ export default class Component { if (node.type === 'VariableDeclaration') { if (node.kind === 'var' || scope === instance_scope) { - node.declarations.forEach((declarator, i) => { - const next = node.declarations[i + 1]; + node.declarations.forEach(declarator => { + // const next = node.declarations[i + 1]; if (declarator.id.type !== 'Identifier') { - const inserts = []; - extract_names(declarator.id).forEach(name => { const variable = component.var_lookup.get(name); if (variable.export_name) { + // TODO is this still true post-#3539? component.error(declarator, { code: 'destructured-prop', message: `Cannot declare props in destructured declaration`, @@ -931,22 +885,10 @@ export default class Component { } if (variable.subscribable) { - inserts.push(get_insert(variable)); + // TODO } }); - if (inserts.length > 0) { - if (next) { - code.overwrite( - declarator.end, - next.start, - `; ${inserts.join('; ')}; ${node.kind} ` - ); - } else { - code.appendLeft(declarator.end, `; ${inserts.join('; ')}`); - } - } - return; } @@ -954,112 +896,43 @@ export default class Component { const variable = component.var_lookup.get(name); if (variable.export_name) { - if (current_group && current_group.kind !== node.kind) { - current_group = null; - } - - const insert = variable.subscribable - ? get_insert(variable) - : null; - - if (!current_group || (current_group.insert && insert)) { - current_group = { - kind: node.kind, - declarators: [declarator], - insert, - }; - coalesced_declarations.push(current_group); - } else if (insert) { - current_group.insert = insert; - current_group.declarators.push(declarator); - } else { - current_group.declarators.push(declarator); - } - - if ( - variable.writable && - variable.name !== variable.export_name - ) { - code.prependRight( - declarator.id.start, - `${variable.export_name}: ` - ); - } - - if (next) { - const next_variable = component.var_lookup.get(next.id.name); - const new_declaration = - !next_variable.export_name || - (current_group.insert && next_variable.subscribable); - - if (new_declaration) { - code.overwrite( - declarator.end, - next.start, - ` ${node.kind} ` - ); - } - } - } else { - current_group = null; - - if (variable.subscribable) { - const insert = get_insert(variable); - - if (next) { - code.overwrite( - declarator.end, - next.start, - `; ${insert}; ${node.kind} ` - ); - } else { - code.appendLeft(declarator.end, `; ${insert}`); - } - } + // const insert = variable.subscribable + // ? get_insert(variable) + // : null; + + declarator.id = { + type: 'ObjectPattern', + properties: [{ + type: 'Property', + method: false, + shorthand: true, + computed: false, + kind: 'init', + key: declarator.id, + value: { + type: 'AssignmentPattern', + left: declarator.id, + right: declarator.init + } + }] + }; + + declarator.init = x`$$props`; } }); } - } else { - if (node.type !== 'ExportNamedDeclaration') { - if (!parent || parent.type === 'Program') current_group = null; - } } }, - leave(node) { + leave(node, _parent, _key, index) { if (map.has(node)) { scope = scope.parent; } - }, - }); - - coalesced_declarations.forEach(group => { - const writable = group.kind === 'var' || group.kind === 'let'; - let c = 0; - let combining = false; - - group.declarators.forEach(declarator => { - const { id } = declarator; - - if (combining) { - code.overwrite(c, id.start, ', '); - } else { - if (writable) code.appendLeft(id.start, '{ '); - combining = true; + if (node.type === 'ExportNamedDeclaration' && node.declaration) { + _parent.body[index] = node.declaration; } - - c = declarator.end; - }); - - if (combining) { - const insert = group.insert ? `; ${group.insert}` : ''; - - const suffix = - `${writable ? ` } = $$props` : ``}${insert}` + - (code.original[c] === ';' ? `` : `;`); - code.appendLeft(c, suffix); - } + }, }); } @@ -1213,8 +1086,6 @@ export default class Component { variable.hoistable = true; hoistable_nodes.add(node); - remove_indentation(this.code, node); - const i = body.indexOf(node); body.splice(i, 1); this.fully_hoisted.push(node); @@ -1280,8 +1151,6 @@ export default class Component { }, }); - add_indentation(this.code, node.body, 2); - const expression = node.body.expression && unwrap_parens(node.body.expression); const declaration = expression && expression.left; diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index 87469309f9..50ff97ef93 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -1,18 +1,18 @@ import Component from '../../Component'; import { walk } from 'estree-walker'; import is_reference from 'is-reference'; -import { b } from 'code-red'; +// import { b } from 'code-red'; import flatten_reference from '../../utils/flatten_reference'; import { create_scopes, Scope, extract_names } from '../../utils/scope'; import { Node } from '../../../interfaces'; -import { globals , sanitize } from '../../../utils/names'; +import { globals } from '../../../utils/names'; import Wrapper from '../../render_dom/wrappers/shared/Wrapper'; import TemplateScope from './TemplateScope'; import get_object from '../../utils/get_object'; import Block from '../../render_dom/Block'; import { INode } from '../interfaces'; import is_dynamic from '../../render_dom/wrappers/shared/is_dynamic'; -import { invalidate } from '../../utils/invalidate'; +// import { invalidate } from '../../utils/invalidate'; const binary_operators: Record = { '**': 15, @@ -224,192 +224,189 @@ export default class Expression { } // TODO move this into a render-dom wrapper? - render(block?: Block) { - if (this.rendered) return this.rendered; - - const { - component, - declarations, - scope_map: map, - template_scope, - owner, - is_synthetic - } = this; - let scope = this.scope; - - const { code } = component; - - let function_expression; - - let dependencies: Set; - let contextual_dependencies: Set; - - // rewrite code as appropriate - walk(this.node, { - enter(node: any, parent: any, key: string) { - // don't manipulate shorthand props twice - if (key === 'value' && parent.shorthand) return; - - code.addSourcemapLocation(node.start); - code.addSourcemapLocation(node.end); - - if (map.has(node)) { - scope = map.get(node); - } - - if (is_reference(node, parent)) { - const { name, nodes } = flatten_reference(node); - - if (scope.has(name)) return; - if (globals.has(name) && !component.var_lookup.has(name)) return; - - if (function_expression) { - if (template_scope.names.has(name)) { - contextual_dependencies.add(name); - - template_scope.dependencies_for_name.get(name).forEach(dependency => { - dependencies.add(dependency); - }); - } else { - dependencies.add(name); - component.add_reference(name); // TODO is this redundant/misplaced? - } - } else if (!is_synthetic && is_contextual(component, template_scope, name)) { - code.prependRight(node.start, key === 'key' && parent.shorthand - ? `${name}: ctx.` - : 'ctx.'); - } - - if (node.type === 'MemberExpression') { - nodes.forEach(node => { - code.addSourcemapLocation(node.start); - code.addSourcemapLocation(node.end); - }); - } - - this.skip(); - } - - if (!function_expression) { - if (node.type === 'AssignmentExpression') { - // TODO should this be a warning/error? `

{foo = 1}

` - } - - if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') { - function_expression = node; - dependencies = new Set(); - contextual_dependencies = new Set(); - } - } - }, - - leave(node: Node, parent: Node) { - if (map.has(node)) scope = scope.parent; - - if (node === function_expression) { - const id = component.get_unique_name( - sanitize(get_function_name(node, owner)) - ); - - const args = contextual_dependencies.size > 0 - ? [`{ ${Array.from(contextual_dependencies).join(', ')} }`] - : []; - - let original_params; - - if (node.params.length > 0) { - original_params = code.slice(node.params[0].start, node.params[node.params.length - 1].end); - args.push(original_params); - } - - const body = code.slice(node.body.start, node.body.end).trim(); - - const fn = node.type === 'FunctionExpression' - ? 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 - component.fully_hoisted.push(fn); - code.overwrite(node.start, node.end, id.name); - - component.add_var({ - name: id.name, - internal: true, - hoistable: true, - referenced: true - }); - } - - else if (contextual_dependencies.size === 0) { - // function can be hoisted inside the component init - component.partly_hoisted.push(fn); - code.overwrite(node.start, node.end, `ctx.${id}`); - - component.add_var({ - name: id.name, - internal: true, - referenced: true - }); - } - - else { - // we need a combo block/init recipe - component.partly_hoisted.push(fn); - code.overwrite(node.start, node.end, id.name); - - component.add_var({ - name: id.name, - internal: true, - referenced: true - }); - - declarations.push(b` - function ${id}(${original_params ? '...args' : ''}) { - return ctx.${id}(ctx${original_params ? ', ...args' : ''}); - } - `); - } - - if (parent && parent.method) { - code.prependRight(node.start, ': '); - } - - function_expression = null; - dependencies = null; - contextual_dependencies = null; - } - - if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') { - const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument; - - // normally (`a = 1`, `b.c = 2`), there'll be a single name - // (a or b). In destructuring cases (`[d, e] = [e, d]`) there - // may be more, in which case we need to tack the extra ones - // onto the initial function call - const names = new Set(extract_names(assignee)); - - const traced: Set = new Set(); - names.forEach(name => { - const dependencies = template_scope.dependencies_for_name.get(name); - if (dependencies) { - dependencies.forEach(name => traced.add(name)); - } else { - traced.add(name); - } - }); - - invalidate(component, scope, code, node, traced); - } - } - }); - - if (declarations.length > 0) { - block.maintain_context = true; - declarations.forEach(declaration => { - block.chunks.init.push(declaration); - }); - } + render(_block?: Block) { + // TODO + + // if (this.rendered) return this.rendered; + + // const { + // component, + // declarations, + // scope_map: map, + // template_scope, + // owner, + // is_synthetic + // } = this; + // let scope = this.scope; + + // let function_expression; + + // let dependencies: Set; + // let contextual_dependencies: Set; + + // // rewrite code as appropriate + // walk(this.node, { + // enter(node: any, parent: any, key: string) { + // // don't manipulate shorthand props twice + // if (key === 'value' && parent.shorthand) return; + + // if (map.has(node)) { + // scope = map.get(node); + // } + + // if (is_reference(node, parent)) { + // const { name, nodes } = flatten_reference(node); + + // if (scope.has(name)) return; + // if (globals.has(name) && !component.var_lookup.has(name)) return; + + // if (function_expression) { + // if (template_scope.names.has(name)) { + // contextual_dependencies.add(name); + + // template_scope.dependencies_for_name.get(name).forEach(dependency => { + // dependencies.add(dependency); + // }); + // } else { + // dependencies.add(name); + // component.add_reference(name); // TODO is this redundant/misplaced? + // } + // } else if (!is_synthetic && is_contextual(component, template_scope, name)) { + // code.prependRight(node.start, key === 'key' && parent.shorthand + // ? `${name}: ctx.` + // : 'ctx.'); + // } + + // if (node.type === 'MemberExpression') { + // nodes.forEach(node => { + // code.addSourcemapLocation(node.start); + // code.addSourcemapLocation(node.end); + // }); + // } + + // this.skip(); + // } + + // if (!function_expression) { + // if (node.type === 'AssignmentExpression') { + // // TODO should this be a warning/error? `

{foo = 1}

` + // } + + // if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') { + // function_expression = node; + // dependencies = new Set(); + // contextual_dependencies = new Set(); + // } + // } + // }, + + // leave(node: Node, parent: Node) { + // if (map.has(node)) scope = scope.parent; + + // if (node === function_expression) { + // const id = component.get_unique_name( + // sanitize(get_function_name(node, owner)) + // ); + + // const args = contextual_dependencies.size > 0 + // ? [`{ ${Array.from(contextual_dependencies).join(', ')} }`] + // : []; + + // let original_params; + + // if (node.params.length > 0) { + // original_params = code.slice(node.params[0].start, node.params[node.params.length - 1].end); + // args.push(original_params); + // } + + // const body = code.slice(node.body.start, node.body.end).trim(); + + // const fn = node.type === 'FunctionExpression' + // ? 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 + // component.fully_hoisted.push(fn); + // code.overwrite(node.start, node.end, id.name); + + // component.add_var({ + // name: id.name, + // internal: true, + // hoistable: true, + // referenced: true + // }); + // } + + // else if (contextual_dependencies.size === 0) { + // // function can be hoisted inside the component init + // component.partly_hoisted.push(fn); + // code.overwrite(node.start, node.end, `ctx.${id}`); + + // component.add_var({ + // name: id.name, + // internal: true, + // referenced: true + // }); + // } + + // else { + // // we need a combo block/init recipe + // component.partly_hoisted.push(fn); + // code.overwrite(node.start, node.end, id.name); + + // component.add_var({ + // name: id.name, + // internal: true, + // referenced: true + // }); + + // declarations.push(b` + // function ${id}(${original_params ? '...args' : ''}) { + // return ctx.${id}(ctx${original_params ? ', ...args' : ''}); + // } + // `); + // } + + // if (parent && parent.method) { + // code.prependRight(node.start, ': '); + // } + + // function_expression = null; + // dependencies = null; + // contextual_dependencies = null; + // } + + // if (node.type === 'AssignmentExpression' || node.type === 'UpdateExpression') { + // const assignee = node.type === 'AssignmentExpression' ? node.left : node.argument; + + // // normally (`a = 1`, `b.c = 2`), there'll be a single name + // // (a or b). In destructuring cases (`[d, e] = [e, d]`) there + // // may be more, in which case we need to tack the extra ones + // // onto the initial function call + // const names = new Set(extract_names(assignee)); + + // const traced: Set = new Set(); + // names.forEach(name => { + // const dependencies = template_scope.dependencies_for_name.get(name); + // if (dependencies) { + // dependencies.forEach(name => traced.add(name)); + // } else { + // traced.add(name); + // } + // }); + + // invalidate(component, scope, code, node, traced); + // } + // } + // }); + + // if (declarations.length > 0) { + // block.maintain_context = true; + // declarations.forEach(declaration => { + // block.chunks.init.push(declaration); + // }); + // } throw new Error(`bad`); @@ -417,29 +414,29 @@ export default class Expression { } } -function get_function_name(_node, parent) { - if (parent.type === 'EventHandler') { - return `${parent.name}_handler`; - } +// function get_function_name(_node, parent) { +// if (parent.type === 'EventHandler') { +// return `${parent.name}_handler`; +// } - if (parent.type === 'Action') { - return `${parent.name}_function`; - } +// if (parent.type === 'Action') { +// return `${parent.name}_function`; +// } - return 'func'; -} +// return 'func'; +// } -function is_contextual(component: Component, scope: TemplateScope, name: string) { - if (name === '$$props') return true; +// function is_contextual(component: Component, scope: TemplateScope, name: string) { +// if (name === '$$props') return true; - // if it's a name below root scope, it's contextual - if (!scope.is_top_level(name)) return true; +// // if it's a name below root scope, it's contextual +// if (!scope.is_top_level(name)) return true; - const variable = component.var_lookup.get(name); +// const variable = component.var_lookup.get(name); - // hoistables, module declarations, and imports are non-contextual - if (!variable || variable.hoistable) return false; +// // hoistables, module declarations, and imports are non-contextual +// if (!variable || variable.hoistable) return false; - // assume contextual - return true; -} +// // assume contextual +// return true; +// } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index f514692bed..d765dbc7d5 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -14,7 +14,7 @@ export default function dom( component: Component, options: CompileOptions ) { - const { name, code } = component; + const { name } = component; const renderer = new Renderer(component, options); const { block } = renderer; @@ -198,7 +198,7 @@ export default function dom( // onto the initial function call const names = new Set(extract_names(assignee)); - invalidate(component, scope, code, node, names); + invalidate(component, scope, node, names); } } }); diff --git a/src/compiler/compile/render_dom/wrappers/DebugTag.ts b/src/compiler/compile/render_dom/wrappers/DebugTag.ts index 6129637e22..c7c0daf890 100644 --- a/src/compiler/compile/render_dom/wrappers/DebugTag.ts +++ b/src/compiler/compile/render_dom/wrappers/DebugTag.ts @@ -2,7 +2,7 @@ import Renderer from '../Renderer'; import Wrapper from './shared/Wrapper'; import Block from '../Block'; import DebugTag from '../../nodes/DebugTag'; -import add_to_set from '../../utils/add_to_set'; +// import add_to_set from '../../utils/add_to_set'; import { b } from 'code-red'; export default class DebugTagWrapper extends Wrapper { @@ -21,11 +21,11 @@ export default class DebugTagWrapper extends Wrapper { render(block: Block, _parent_node: string, _parent_nodes: string) { const { renderer } = this; - const { component } = renderer; + // const { component } = renderer; if (!renderer.options.dev) return; - const { var_lookup } = component; + // const { var_lookup } = component; if (this.node.expressions.length === 0) { // Debug all @@ -37,43 +37,45 @@ export default class DebugTagWrapper extends Wrapper { block.chunks.create.push(b`debugger`); block.chunks.update.push(b`debugger`); } else { - const { code } = component; - code.overwrite(this.node.start + 1, this.node.start + 7, 'log', { - storeName: true - }); - const log = `[✂${this.node.start + 1}-${this.node.start + 7}✂]`; + // TODO - const dependencies = new Set(); - this.node.expressions.forEach(expression => { - add_to_set(dependencies, expression.dependencies); - }); + // const { code } = component; + // code.overwrite(this.node.start + 1, this.node.start + 7, 'log', { + // storeName: true + // }); + // const log = `[✂${this.node.start + 1}-${this.node.start + 7}✂]`; + + // const dependencies = new Set(); + // this.node.expressions.forEach(expression => { + // add_to_set(dependencies, expression.dependencies); + // }); - const condition = Array.from(dependencies).map(d => `changed.${d}`).join(' || '); + // const condition = Array.from(dependencies).map(d => `changed.${d}`).join(' || '); - const ctx_identifiers = this.node.expressions - .filter(e => { - const looked_up_var = var_lookup.get(e.node.name); - return !(looked_up_var && looked_up_var.hoistable); - }) - .map(e => e.node.name) - .join(', '); - const logged_identifiers = this.node.expressions.map(e => e.node.name).join(', '); + // const ctx_identifiers = this.node.expressions + // .filter(e => { + // const looked_up_var = var_lookup.get(e.node.name); + // return !(looked_up_var && looked_up_var.hoistable); + // }) + // .map(e => e.node.name) + // .join(', '); + // const logged_identifiers = this.node.expressions.map(e => e.node.name).join(', '); - block.chunks.update.push(b` - if (${condition}) { - const { ${ctx_identifiers} } = ctx; - @_console.${log}({ ${logged_identifiers} }); - debugger; - } - `); + // block.chunks.update.push(b` + // if (${condition}) { + // const { ${ctx_identifiers} } = ctx; + // @_console.${log}({ ${logged_identifiers} }); + // debugger; + // } + // `); - block.chunks.create.push(b` - { - const { ${ctx_identifiers} } = ctx; - @_console.${log}({ ${logged_identifiers} }); - debugger; - } - `); + // block.chunks.create.push(b` + // { + // const { ${ctx_identifiers} } = ctx; + // @_console.${log}({ ${logged_identifiers} }); + // debugger; + // } + // `); } } } diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 2ce1f11a4f..c29f935132 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -104,11 +104,12 @@ export default class EachBlockWrapper extends Wrapper { ? node.expression.node.elements.length : null; + // TODO // hack the sourcemap, so that if data is missing the bug // is easy to find let c = this.node.start + 2; while (renderer.component.source[c] !== 'e') c += 1; - renderer.component.code.overwrite(c, c + 4, 'length'); + // renderer.component.code.overwrite(c, c + 4, 'length'); const each_block_value = renderer.component.get_unique_name(`${this.var}_value`); const iterations = block.get_unique_name(`${this.var}_blocks`); diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index c3134a9be4..99413ee314 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -18,7 +18,7 @@ export default class MustacheTagWrapper extends Tag { render(block: Block, parent_node: string, parent_nodes: string) { const { init } = this.rename_this_method( block, - value => `@set_data(${this.var}, ${value});` + value => x`@set_data(${this.var}, ${value});` ); block.add_element( diff --git a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts index b2c0fc86cf..3a05a3c1d3 100644 --- a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts @@ -46,7 +46,7 @@ export default class RawMustacheTagWrapper extends Tag { const { init } = this.rename_this_method( block, - content => `${html_tag}.p(${content});` + content => x`${html_tag}.p(${content});` ); const update_anchor = in_head ? 'null' : needs_anchor ? html_anchor : this.next ? this.next.var : 'null'; diff --git a/src/compiler/compile/render_dom/wrappers/shared/Tag.ts b/src/compiler/compile/render_dom/wrappers/shared/Tag.ts index b67617965a..6ee900f2e9 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/Tag.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/Tag.ts @@ -4,6 +4,7 @@ import Renderer from '../../Renderer'; import Block from '../../Block'; import MustacheTag from '../../../nodes/MustacheTag'; import RawMustacheTag from '../../../nodes/RawMustacheTag'; +import { Node } from '../../../../interfaces'; export default class Tag extends Wrapper { node: MustacheTag | RawMustacheTag; @@ -17,7 +18,7 @@ export default class Tag extends Wrapper { rename_this_method( block: Block, - update: ((value: string) => string) + update: ((value: Node) => Node) ) { const dependencies = this.node.expression.dynamic_dependencies(); const snippet = this.node.expression.node; diff --git a/src/compiler/compile/utils/invalidate.ts b/src/compiler/compile/utils/invalidate.ts index 55f5d49977..2eae0766d7 100644 --- a/src/compiler/compile/utils/invalidate.ts +++ b/src/compiler/compile/utils/invalidate.ts @@ -1,66 +1,67 @@ import Component from '../Component'; -import MagicString from 'magic-string'; import { Node } from '../../interfaces'; -import { nodes_match } from '../../utils/nodes_match'; +// import { nodes_match } from '../../utils/nodes_match'; import { Scope } from './scope'; -export function invalidate(component: Component, scope: Scope, code: MagicString, node: Node, names: Set) { - const [head, ...tail] = Array.from(names).filter(name => { - const owner = scope.find_owner(name); - if (owner && owner !== component.instance_scope) return false; +export function invalidate(_component: Component, _scope: Scope, _node: Node, _names: Set) { + // const [head, ...tail] = Array.from(names).filter(name => { + // const owner = scope.find_owner(name); + // if (owner && owner !== component.instance_scope) return false; - const variable = component.var_lookup.get(name); + // const variable = component.var_lookup.get(name); - return variable && ( - !variable.hoistable && - !variable.global && - !variable.module && - ( - variable.referenced || - variable.is_reactive_dependency || - variable.export_name || - variable.name[0] === '$' - ) - ); - }); + // return variable && ( + // !variable.hoistable && + // !variable.global && + // !variable.module && + // ( + // variable.referenced || + // variable.is_reactive_dependency || + // variable.export_name || + // variable.name[0] === '$' + // ) + // ); + // }); - if (head) { - component.has_reactive_assignments = true; + // TODO - if (node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) { - code.overwrite(node.start, node.end, component.invalidate(head)); - } else { - let suffix = ')'; + // if (head) { + // component.has_reactive_assignments = true; - if (head[0] === '$') { - code.prependRight(node.start, `${component.helper('set_store_value')}(${head.slice(1)}, `); - } else { - let prefix = `$$invalidate`; + // if (node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) { + // code.overwrite(node.start, node.end, component.invalidate(head)); + // } else { + // let suffix = ')'; - const variable = component.var_lookup.get(head); - if (variable.subscribable && variable.reassigned) { - prefix = `$$subscribe_${head}($$invalidate`; - suffix += `)`; - } + // if (head[0] === '$') { + // code.prependRight(node.start, `${component.helper('set_store_value')}(${head.slice(1)}, `); + // } else { + // let prefix = `$$invalidate`; - code.prependRight(node.start, `${prefix}('${head}', `); - } + // const variable = component.var_lookup.get(head); + // if (variable.subscribable && variable.reassigned) { + // prefix = `$$subscribe_${head}($$invalidate`; + // suffix += `)`; + // } - const extra_args = tail.map(name => component.invalidate(name)); + // code.prependRight(node.start, `${prefix}('${head}', `); + // } - const pass_value = ( - extra_args.length > 0 || - (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || - (node.type === 'UpdateExpression' && !node.prefix) - ); + // const extra_args = tail.map(name => component.invalidate(name)); - if (pass_value) { - extra_args.unshift(head); - } + // const pass_value = ( + // extra_args.length > 0 || + // (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || + // (node.type === 'UpdateExpression' && !node.prefix) + // ); - suffix = `${extra_args.map(arg => `, ${arg}`).join('')}${suffix}`; + // if (pass_value) { + // extra_args.unshift(head); + // } - code.appendLeft(node.end, suffix); - } - } + // suffix = `${extra_args.map(arg => `, ${arg}`).join('')}${suffix}`; + + // code.appendLeft(node.end, suffix); + // } + // } } \ No newline at end of file diff --git a/src/compiler/utils/indentation.ts b/src/compiler/utils/indentation.ts deleted file mode 100644 index 54ededc37d..0000000000 --- a/src/compiler/utils/indentation.ts +++ /dev/null @@ -1,57 +0,0 @@ -import MagicString from 'magic-string'; -import { Node } from '../interfaces'; -import { walk } from 'estree-walker'; -import repeat from './repeat'; - -export function remove_indentation(code: MagicString, node: Node) { - const indent = code.getIndentString(); - const pattern = new RegExp(`^${indent}`, 'gm'); - - const excluded = []; - - walk(node, { - enter(node) { - if (node.type === 'TemplateElement') { - excluded.push(node); - } - } - }); - - const str = code.original.slice(node.start, node.end); - - let match; - while (match = pattern.exec(str)) { - const index = node.start + match.index; - while (excluded[0] && excluded[0].end < index) excluded.shift(); - if (excluded[0] && excluded[0].start < index) continue; - - code.remove(index, index + indent.length); - } -} - -export function add_indentation(code: MagicString, node: Node, levels = 1) { - const base_indent = code.getIndentString(); - const indent = repeat(base_indent, levels); - const pattern = /\n/gm; - - const excluded = []; - - walk(node, { - enter(node) { - if (node.type === 'TemplateElement') { - excluded.push(node); - } - } - }); - - const str = code.original.slice(node.start, node.end); - - let match; - while (match = pattern.exec(str)) { - const index = node.start + match.index; - while (excluded[0] && excluded[0].end < index) excluded.shift(); - if (excluded[0] && excluded[0].start < index) continue; - - code.appendLeft(index + 1, indent); - } -} diff --git a/test/runtime/samples/_/main.svelte b/test/runtime/samples/_/main.svelte index 22b3c84db0..41e3ddf043 100644 --- a/test/runtime/samples/_/main.svelte +++ b/test/runtime/samples/_/main.svelte @@ -1,5 +1,5 @@

Hello {name}!

\ No newline at end of file