diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index b6d5eb49ca..29e05c7987 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -299,6 +299,11 @@ export default class Component { walk(program, { enter: (node) => { + if (node.type === 'Identifier' && !('name' in node)) { + console.log(node); + throw new Error('wtf'); + } + if (node.type === 'Identifier' && node.name[0] === '@') { // TODO temp if (!/@\w+$/.test(node.name)) { diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 65f32d072d..386611df79 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -202,11 +202,6 @@ export default class Block { } add_variable(id: Identifier, init?: Node) { - if (id.name[0] === '#') { - // TODO is this still necessary? - id.name = this.alias(id.name.slice(1)).name; - } - this.variables.forEach(v => { if (v.id.name === id.name) { throw new Error( @@ -371,8 +366,7 @@ export default class Block { // TODO should code-red do this automatically? probably return_value.properties = return_value.properties.filter(prop => prop.value); - /* eslint-disable @typescript-eslint/indent,indent */ - return b` + const body = b` ${Array.from(this.variables.values()).map(({ id, init }) => { return init ? b`let ${id} = ${init}` @@ -390,7 +384,8 @@ export default class Block { return ${return_value};` } `; - /* eslint-enable @typescript-eslint/indent,indent */ + + return body; } render() { diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 5fd0d294ee..8b4a3024da 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -4,7 +4,6 @@ import Component from '../Component'; import Renderer from './Renderer'; import { CompileOptions } from '../../interfaces'; import { walk } from 'estree-walker'; -import { stringify_props } from '../utils/stringify_props'; import add_to_set from '../utils/add_to_set'; import { extract_names } from '../utils/scope'; import { invalidate } from '../utils/invalidate'; @@ -372,6 +371,19 @@ export default function dom( `; } + const return_value = { + type: 'ObjectExpression', + properties: filtered_declarations.map(name => { + const id = { type: 'Identifier', name }; + return { + type: 'Property', + key: id, + value: id, + kind: 'init' + }; + }) + }; + body.push(b` function ${definition}(${args.join(', ')}) { ${reactive_store_declarations.length > 0 && `let ${reactive_store_declarations.join(', ')};`} @@ -406,7 +418,7 @@ export default function dom( ${fixed_reactive_declarations} - return ${stringify_props(filtered_declarations)}; + return ${return_value}; } `); } @@ -476,9 +488,9 @@ export default function dom( class ${name} extends ${superclass} { constructor(options) { super(${options.dev && `options`}); - ${should_add_css && `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`} + ${should_add_css && b`if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`} @init(this, options, ${definition}, create_fragment, ${not_equal}, ${prop_names}); - ${options.dev && `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name}", options, id: create_fragment.name });`} + ${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name}", options, id: create_fragment.name });`} ${dev_props_check} } diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index 0af686e443..8c1891aa32 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -2,7 +2,7 @@ import Attribute from '../../../nodes/Attribute'; import Block from '../../Block'; import fix_attribute_casing from './fix_attribute_casing'; import ElementWrapper from './index'; -import { stringify } from '../../../utils/stringify'; +import { string_literal } from '../../../utils/stringify'; import { b, x } from 'code-red'; import Expression from '../../../nodes/shared/Expression'; import Text from '../../../nodes/Text'; @@ -172,8 +172,8 @@ export default class AttributeWrapper { is_legacy_input_type ? b`@set_input_type(${element.var}, ${value});` : property_name - ? b`${element.var}.${property_name} = ${value};` - : b`${method}(${element.var}, "${name}", ${value === true ? '""' : value});` + ? b`${element.var}.${property_name} = ${value === true ? { type: 'Literal', value: true } : value};` + : b`${method}(${element.var}, "${name}", ${value === true ? x`""` : value});` ); block.chunks.hydrate.push(statement); @@ -207,7 +207,7 @@ export default class AttributeWrapper { render_chunks() { return this.node.chunks.map((chunk) => { if (chunk.type === 'Text') { - return stringify(chunk.data); + return string_literal(chunk.data); } return chunk.manipulate(); diff --git a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts index 994354037f..4ad6ae1a0d 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts @@ -8,12 +8,7 @@ import Renderer from '../../Renderer'; import flatten_reference from '../../../utils/flatten_reference'; import EachBlock from '../../../nodes/EachBlock'; import { Node as INode, Identifier } from '../../../../interfaces'; - -function get_tail(node: INode) { - const end = node.end; - while (node.type === 'MemberExpression') node = node.object; - return { start: node.end, end }; -} +import { changed } from '../shared/changed'; export default class BindingWrapper { node: Binding; @@ -22,9 +17,9 @@ export default class BindingWrapper { object: string; handler: { uses_context: boolean; - mutation: string; + mutation: Node; contextual_dependencies: Set; - snippet?: string; + snippet?: Node; }; snippet: INode; is_readonly: boolean; @@ -59,7 +54,7 @@ export default class BindingWrapper { // TODO unfortunate code is necessary because we need to use `ctx` // inside the fragment, but not inside the