From 1dffd3571fe5b2a2ac07e0c5290358457f484484 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Thu, 6 Apr 2017 10:27:23 -0400 Subject: [PATCH] horrible half-finished commit so I can work on this on another machine --- src/generators/Generator.js | 4 +- src/generators/dom/fragment.js | 85 ++++++ src/generators/dom/index.js | 273 +++++++++--------- src/generators/dom/visit.js | 4 +- src/generators/dom/visitors/Component.js | 2 +- src/generators/dom/visitors/EachBlock.js | 2 +- src/generators/dom/visitors/Element.js | 127 ++++---- src/generators/dom/visitors/IfBlock.js | 2 +- src/generators/dom/visitors/MustacheTag.js | 18 +- src/generators/dom/visitors/RawMustacheTag.js | 10 +- src/generators/dom/visitors/Text.js | 6 +- src/generators/dom/visitors/YieldTag.js | 2 +- .../attributes/addElementAttributes.js | 66 ++--- src/generators/dom/visitors/meta/Window.js | 2 +- test/runtime/index.js | 2 +- .../samples/attribute-dynamic/_config.js | 2 + 16 files changed, 353 insertions(+), 254 deletions(-) create mode 100644 src/generators/dom/fragment.js diff --git a/src/generators/Generator.js b/src/generators/Generator.js index d1956ed73460..74c0fda324a8 100644 --- a/src/generators/Generator.js +++ b/src/generators/Generator.js @@ -62,14 +62,14 @@ export default class Generator { return alias; } - contextualise ( expression, isEventHandler ) { + contextualise ( fragment, expression, isEventHandler ) { this.addSourcemapLocations( expression ); const usedContexts = []; const dependencies = []; const { code, helpers } = this; - const { contextDependencies, contexts, indexes } = this.current; + const { contextDependencies, contexts, indexes } = fragment; let scope = annotateWithScopes( expression ); diff --git a/src/generators/dom/fragment.js b/src/generators/dom/fragment.js new file mode 100644 index 000000000000..6c628e1c059d --- /dev/null +++ b/src/generators/dom/fragment.js @@ -0,0 +1,85 @@ +import CodeBuilder from '../../utils/CodeBuilder.js'; +import deindent from '../../utils/deindent.js'; + +export class Block { + constructor ({ generator, namespace, node, params, target }) { + this.generator = generator; + this.namespace = namespace; + this.node = node; + this.target = target; + + this.create = new CodeBuilder(); + this.mount = new CodeBuilder(); + this.update = new CodeBuilder(); + this.destroy = new CodeBuilder(); + + this.contexts = new Map(); + this.indexes = new Map(); + + this.getUniqueName = generator.getUniqueNameMaker( params ); + } + + contextualise ( expression, isEventHandler ) { + return this.generator.contextualise( this, expression, isEventHandler ); + } + + createElement ( name ) { + return new Element({ + generator: this.generator, + nodeName: name, + name: this.getUniqueName( name ), + namespace: name === 'svg' ? 'http://www.w3.org/2000/svg' : this.namespace, + parent: this + }); + } +} + +class Element { + constructor ({ generator, name, namespace, nodeName, parent }) { + this.generator = generator; + this.name = name; + this.namespace = namespace; + this.nodeName = nodeName; + this.parent = parent; + + this.create = new CodeBuilder(); + this.update = new CodeBuilder(); + this.destroy = new CodeBuilder(); + + let render; + + if ( namespace ) { + if ( namespace === 'http://www.w3.org/2000/svg' ) { + render = `var ${name} = ${generator.helper( 'createSvgElement' )}( '${nodeName}' )`; + } else { + render = `var ${name} = document.createElementNS( '${namespace}', '${nodeName}' );`; + } + } else { + render = `var ${name} = ${generator.helper( 'createElement' )}( '${nodeName}' );`; + } + + if ( generator.cssId && !generator.elementDepth ) { + render += `\n${generator.helper( 'setAttribute' )}( ${name}, '${generator.cssId}', '' );`; + } + + this.create.addLine( render ); + } + + apply () { + this.parent.create.addBlock( this.init ); + if ( !this.update.isEmpty() ) this.parent.update.addBlock( this.update ); + if ( !this.destroy.isEmpty() ) this.parent.destroy.addBlock( this.destroy ); + + const parent = this.parent; // TODO could be ancestor... + + if ( parent.target === 'target' ) { + parent.mount.addLine( `${this.generator.helper( 'insertNode' )}( ${this.name}, target, anchor );` ); + } else { + parent.create.addLine( `${this.generator.helper( 'appendNode' )}( ${this.name}, ${parent.target} );` ); + } + } + + contextualise ( expression, isEventHandler ) { + return this.parent.contextualise( expression, isEventHandler ); + } +} \ No newline at end of file diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index 3e86ead4352c..daaae8650670 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -3,6 +3,7 @@ import getBuilders from './utils/getBuilders.js'; import CodeBuilder from '../../utils/CodeBuilder.js'; import visit from './visit.js'; import Generator from '../Generator.js'; +import { Block } from './fragment.js'; import * as shared from '../../shared/index.js'; class DomGenerator extends Generator { @@ -17,122 +18,122 @@ class DomGenerator extends Generator { }; } - addElement ( name, renderStatement, needsIdentifier = false ) { - const isToplevel = this.current.localElementDepth === 0; - if ( needsIdentifier || isToplevel ) { - this.current.builders.init.addLine( - `var ${name} = ${renderStatement};` - ); - - this.createMountStatement( name ); - } else { - this.current.builders.init.addLine( `${this.helper( 'appendNode' )}( ${renderStatement}, ${this.current.target} );` ); - } - - if ( isToplevel ) { - this.current.builders.detach.addLine( `${this.helper( 'detachNode' )}( ${name} );` ); - } - } - - addRenderer ( fragment ) { - if ( fragment.autofocus ) { - fragment.builders.init.addLine( `${fragment.autofocus}.focus();` ); - } - - // minor hack – we need to ensure that any {{{triples}}} are detached - // first, so we append normal detach statements to detachRaw - fragment.builders.detachRaw.addBlock( fragment.builders.detach ); - - if ( !fragment.builders.detachRaw.isEmpty() ) { - fragment.builders.teardown.addBlock( deindent` - if ( detach ) { - ${fragment.builders.detachRaw} - } - ` ); - } - - const properties = new CodeBuilder(); - - let localKey; - if ( fragment.key ) { - localKey = fragment.getUniqueName( 'key' ); - properties.addBlock( `key: ${localKey},` ); - } - - if ( fragment.builders.mount.isEmpty() ) { - properties.addBlock( `mount: ${this.helper( 'noop' )},` ); - } else { - properties.addBlock( deindent` - mount: function ( target, anchor ) { - ${fragment.builders.mount} - }, - ` ); - } - - if ( fragment.builders.update.isEmpty() ) { - properties.addBlock( `update: ${this.helper( 'noop' )},` ); - } else { - properties.addBlock( deindent` - update: function ( changed, ${fragment.params.join( ', ' )} ) { - ${fragment.tmp ? `var ${fragment.tmp};` : ''} - - ${fragment.builders.update} - }, - ` ); - } - - if ( fragment.builders.teardown.isEmpty() ) { - properties.addBlock( `teardown: ${this.helper( 'noop' )},` ); - } else { - properties.addBlock( deindent` - teardown: function ( detach ) { - ${fragment.builders.teardown} - } - ` ); - } - - this.renderers.push( deindent` - function ${fragment.name} ( ${fragment.params.join( ', ' )}, ${fragment.component}${fragment.key ? `, ${localKey}` : ''} ) { - ${fragment.builders.init} - - return { - ${properties} - }; - } - ` ); - } - - createAnchor ( name ) { - const renderStatement = `${this.helper( 'createComment' )}()`; - this.addElement( name, renderStatement, true ); - } - - createMountStatement ( name ) { - if ( this.current.target === 'target' ) { - this.current.builders.mount.addLine( `${this.helper( 'insertNode' )}( ${name}, target, anchor );` ); - } else { - this.current.builders.init.addLine( `${this.helper( 'appendNode' )}( ${name}, ${this.current.target} );` ); - } - } - - generateBlock ( node, name, type ) { - this.push({ - type, - name, - target: 'target', - localElementDepth: 0, - builders: getBuilders(), - getUniqueName: this.getUniqueNameMaker( this.current.params ) - }); - - // walk the children here - node.children.forEach( node => visit( node, this ) ); - this.addRenderer( this.current ); - this.pop(); - - // unset the children, to avoid them being visited again - node.children = []; - } + // addElement ( name, renderStatement, needsIdentifier = false ) { + // const isToplevel = this.current.localElementDepth === 0; + // if ( needsIdentifier || isToplevel ) { + // this.current.builders.init.addLine( + // `var ${name} = ${renderStatement};` + // ); + + // this.createMountStatement( name ); + // } else { + // this.current.builders.init.addLine( `${this.helper( 'appendNode' )}( ${renderStatement}, ${this.current.target} );` ); + // } + + // if ( isToplevel ) { + // this.current.builders.detach.addLine( `${this.helper( 'detachNode' )}( ${name} );` ); + // } + // } + + // addRenderer ( fragment ) { + // if ( fragment.autofocus ) { + // fragment.builders.init.addLine( `${fragment.autofocus}.focus();` ); + // } + + // // minor hack – we need to ensure that any {{{triples}}} are detached + // // first, so we append normal detach statements to detachRaw + // fragment.builders.detachRaw.addBlock( fragment.builders.detach ); + + // if ( !fragment.builders.detachRaw.isEmpty() ) { + // fragment.builders.teardown.addBlock( deindent` + // if ( detach ) { + // ${fragment.builders.detachRaw} + // } + // ` ); + // } + + // const properties = new CodeBuilder(); + + // let localKey; + // if ( fragment.key ) { + // localKey = fragment.getUniqueName( 'key' ); + // properties.addBlock( `key: ${localKey},` ); + // } + + // if ( fragment.builders.mount.isEmpty() ) { + // properties.addBlock( `mount: ${this.helper( 'noop' )},` ); + // } else { + // properties.addBlock( deindent` + // mount: function ( target, anchor ) { + // ${fragment.builders.mount} + // }, + // ` ); + // } + + // if ( fragment.builders.update.isEmpty() ) { + // properties.addBlock( `update: ${this.helper( 'noop' )},` ); + // } else { + // properties.addBlock( deindent` + // update: function ( changed, ${fragment.params.join( ', ' )} ) { + // ${fragment.tmp ? `var ${fragment.tmp};` : ''} + + // ${fragment.builders.update} + // }, + // ` ); + // } + + // if ( fragment.builders.teardown.isEmpty() ) { + // properties.addBlock( `teardown: ${this.helper( 'noop' )},` ); + // } else { + // properties.addBlock( deindent` + // teardown: function ( detach ) { + // ${fragment.builders.teardown} + // } + // ` ); + // } + + // this.renderers.push( deindent` + // function ${fragment.name} ( ${fragment.params.join( ', ' )}, ${fragment.component}${fragment.key ? `, ${localKey}` : ''} ) { + // ${fragment.builders.init} + + // return { + // ${properties} + // }; + // } + // ` ); + // } + + // createAnchor ( name ) { + // const renderStatement = `${this.helper( 'createComment' )}()`; + // this.addElement( name, renderStatement, true ); + // } + + // createMountStatement ( name ) { + // if ( this.current.target === 'target' ) { + // this.current.builders.mount.addLine( `${this.helper( 'insertNode' )}( ${name}, target, anchor );` ); + // } else { + // this.current.builders.init.addLine( `${this.helper( 'appendNode' )}( ${name}, ${this.current.target} );` ); + // } + // } + + // generateBlock ( node, name, type ) { + // this.push({ + // type, + // name, + // target: 'target', + // localElementDepth: 0, + // builders: getBuilders(), + // getUniqueName: this.getUniqueNameMaker( this.current.params ) + // }); + + // // walk the children here + // node.children.forEach( node => visit( node, this ) ); + // this.addRenderer( this.current ); + // this.pop(); + + // // unset the children, to avoid them being visited again + // node.children = []; + // } helper ( name ) { if ( this.options.dev && `${name}Dev` in shared ) { @@ -156,29 +157,37 @@ export default function dom ( parsed, source, options ) { const getUniqueName = generator.getUniqueNameMaker( [ 'root' ] ); const component = getUniqueName( 'component' ); - generator.push({ - type: 'block', - name: generator.alias( 'render_main_fragment' ), + const mainFragment = new Block({ + generator, + name: 'create_main_fragment', namespace, - target: 'target', - localElementDepth: 0, - key: null, + params: [ 'root' ], + target: 'target' + }); - component, + // generator.push({ + // type: 'block', + // name: generator.alias( 'render_main_fragment' ), + // namespace, + // target: 'target', + // localElementDepth: 0, + // key: null, - contexts: new Map(), - indexes: new Map(), + // component, - params: [ 'root' ], - indexNames: new Map(), - listNames: new Map(), + // contexts: new Map(), + // indexes: new Map(), - builders: getBuilders(), - getUniqueName, - }); + // params: [ 'root' ], + // indexNames: new Map(), + // listNames: new Map(), + + // builders: getBuilders(), + // getUniqueName, + // }); parsed.html.children.forEach( node => { - visit( node, generator ); + visit( generator, mainFragment, node ); }); generator.addRenderer( generator.pop() ); diff --git a/src/generators/dom/visit.js b/src/generators/dom/visit.js index e9837098c4cd..1b96ed510ba6 100644 --- a/src/generators/dom/visit.js +++ b/src/generators/dom/visit.js @@ -1,6 +1,6 @@ import visitors from './visitors/index.js'; -export default function visit ( node, generator ) { +export default function visit ( generator, fragment, node ) { const visitor = visitors[ node.type ]; - visitor( generator, node ); + visitor( generator, fragment, node ); } \ No newline at end of file diff --git a/src/generators/dom/visitors/Component.js b/src/generators/dom/visitors/Component.js index 1733886fda5f..86cc4cd38fe4 100644 --- a/src/generators/dom/visitors/Component.js +++ b/src/generators/dom/visitors/Component.js @@ -19,7 +19,7 @@ function stringifyProps ( props ) { return `{ ${joined} }`; } -export default function visitComponent ( generator, node ) { +export default function visitComponent ( generator, fragment, node ) { const hasChildren = node.children.length > 0; const { current } = generator; const name = current.getUniqueName( capDown( node.name === ':Self' ? generator.name : node.name ) ); diff --git a/src/generators/dom/visitors/EachBlock.js b/src/generators/dom/visitors/EachBlock.js index d60c69ec8b92..04b8b2fe1d1a 100644 --- a/src/generators/dom/visitors/EachBlock.js +++ b/src/generators/dom/visitors/EachBlock.js @@ -3,7 +3,7 @@ import deindent from '../../../utils/deindent.js'; import getBuilders from '../utils/getBuilders.js'; import visit from '../visit.js'; -export default function visitEachBlock ( generator, node ) { +export default function visitEachBlock ( generator, fragment, node ) { const name = generator.getUniqueName( `each_block` ); const renderer = generator.getUniqueName( `render_each_block` ); const elseName = generator.getUniqueName( `${name}_else` ); diff --git a/src/generators/dom/visitors/Element.js b/src/generators/dom/visitors/Element.js index 21f81c8eb9d6..f84768285393 100644 --- a/src/generators/dom/visitors/Element.js +++ b/src/generators/dom/visitors/Element.js @@ -9,7 +9,7 @@ const meta = { ':Window': visitWindow }; -export default function visitElement ( generator, node ) { +export default function visitElement ( generator, fragment, node ) { if ( node.name in meta ) { return meta[ node.name ]( generator, node ); } @@ -18,69 +18,69 @@ export default function visitElement ( generator, node ) { return visitComponent( generator, node ); } - const name = generator.current.getUniqueName( node.name ); + const elementFragment = fragment.createElement( node.name ); - const local = { - name, - namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : generator.current.namespace, - isComponent: false, + // const local = { + // name, + // namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : generator.current.namespace, + // isComponent: false, - allUsedContexts: [], + // allUsedContexts: [], - init: new CodeBuilder(), - update: new CodeBuilder(), - teardown: new CodeBuilder() - }; + // init: new CodeBuilder(), + // update: new CodeBuilder(), + // teardown: new CodeBuilder() + // }; - const isToplevel = generator.current.localElementDepth === 0; + const isToplevel = fragment.localElementDepth === 0; - addElementAttributes( generator, node, local ); + addElementAttributes( generator, elementFragment, node ); - if ( local.allUsedContexts.length ) { - const initialProps = local.allUsedContexts.map( contextName => { - if ( contextName === 'root' ) return `root: root`; + // if ( local.allUsedContexts.length ) { + // const initialProps = local.allUsedContexts.map( contextName => { + // if ( contextName === 'root' ) return `root: root`; - const listName = generator.current.listNames.get( contextName ); - const indexName = generator.current.indexNames.get( contextName ); + // const listName = generator.current.listNames.get( contextName ); + // const indexName = generator.current.indexNames.get( contextName ); - return `${listName}: ${listName},\n${indexName}: ${indexName}`; - }).join( ',\n' ); + // return `${listName}: ${listName},\n${indexName}: ${indexName}`; + // }).join( ',\n' ); - const updates = local.allUsedContexts.map( contextName => { - if ( contextName === 'root' ) return `${name}.__svelte.root = root;`; + // const updates = local.allUsedContexts.map( contextName => { + // if ( contextName === 'root' ) return `${name}.__svelte.root = root;`; - const listName = generator.current.listNames.get( contextName ); - const indexName = generator.current.indexNames.get( contextName ); + // const listName = generator.current.listNames.get( contextName ); + // const indexName = generator.current.indexNames.get( contextName ); - return `${name}.__svelte.${listName} = ${listName};\n${name}.__svelte.${indexName} = ${indexName};`; - }).join( '\n' ); + // return `${name}.__svelte.${listName} = ${listName};\n${name}.__svelte.${indexName} = ${indexName};`; + // }).join( '\n' ); - local.init.addBlock( deindent` - ${name}.__svelte = { - ${initialProps} - }; - ` ); + // local.init.addBlock( deindent` + // ${name}.__svelte = { + // ${initialProps} + // }; + // ` ); - local.update.addBlock( updates ); - } + // local.update.addBlock( updates ); + // } - let render; + // let render; - if ( local.namespace ) { - if ( local.namespace === 'http://www.w3.org/2000/svg' ) { - render = `var ${name} = ${generator.helper( 'createSvgElement' )}( '${node.name}' )`; - } else { - render = `var ${name} = document.createElementNS( '${local.namespace}', '${node.name}' );`; - } - } else { - render = `var ${name} = ${generator.helper( 'createElement' )}( '${node.name}' );`; - } + // if ( elementFragment.namespace ) { + // if ( elementFragment.namespace === 'http://www.w3.org/2000/svg' ) { + // render = `var ${elementFragment.name} = ${generator.helper( 'createSvgElement' )}( '${node.name}' )`; + // } else { + // render = `var ${elementFragment.name} = document.createElementNS( '${elementFragment.namespace}', '${node.name}' );`; + // } + // } else { + // render = `var ${elementFragment.name} = ${generator.helper( 'createElement' )}( '${node.name}' );`; + // } - if ( generator.cssId && !generator.elementDepth ) { - render += `\n${generator.helper( 'setAttribute' )}( ${name}, '${generator.cssId}', '' );`; - } + // if ( generator.cssId && !generator.elementDepth ) { + // render += `\n${generator.helper( 'setAttribute' )}( ${name}, '${generator.cssId}', '' );`; + // } - local.init.addLineAtStart( render ); + // local.init.addLineAtStart( render ); if ( isToplevel ) { generator.current.builders.detach.addLine( `${generator.helper( 'detachNode' )}( ${name} );` ); } @@ -92,28 +92,31 @@ export default function visitElement ( generator, node ) { node.initialUpdate = statement; } - generator.current.builders.init.addBlock( local.init ); - if ( !local.update.isEmpty() ) generator.current.builders.update.addBlock( local.update ); - if ( !local.teardown.isEmpty() ) generator.current.builders.teardown.addBlock( local.teardown ); + // TODO this is badly named + elementFragment.apply(); - generator.createMountStatement( name ); + // generator.current.builders.init.addBlock( local.init ); + // if ( !local.update.isEmpty() ) generator.current.builders.update.addBlock( local.update ); + // if ( !local.teardown.isEmpty() ) generator.current.builders.teardown.addBlock( local.teardown ); - generator.push({ - type: 'element', - namespace: local.namespace, - target: name, - parent: generator.current, - localElementDepth: generator.current.localElementDepth + 1, - key: null - }); + // generator.createMountStatement( elementFragment.name ); + + // generator.push({ + // type: 'element', + // namespace: local.namespace, + // target: name, + // parent: generator.current, + // localElementDepth: generator.current.localElementDepth + 1, + // key: null + // }); - generator.elementDepth += 1; + // generator.elementDepth += 1; node.children.forEach( child => { - visit( child, generator ); + visit( generator, elementFragment, child ); }); - generator.elementDepth -= 1; + // generator.elementDepth -= 1; if ( node.initialUpdate ) { generator.current.builders.init.addBlock( node.initialUpdate ); diff --git a/src/generators/dom/visitors/IfBlock.js b/src/generators/dom/visitors/IfBlock.js index aa1c15d7d1ba..b33836519ff4 100644 --- a/src/generators/dom/visitors/IfBlock.js +++ b/src/generators/dom/visitors/IfBlock.js @@ -30,7 +30,7 @@ function getConditionsAndBlocks ( generator, node, _name, i = 0 ) { return conditionsAndBlocks; } -export default function visitIfBlock ( generator, node ) { +export default function visitIfBlock ( generator, fragment, node ) { const params = generator.current.params.join( ', ' ); const name = generator.getUniqueName( `if_block` ); const getBlock = generator.current.getUniqueName( `get_block` ); diff --git a/src/generators/dom/visitors/MustacheTag.js b/src/generators/dom/visitors/MustacheTag.js index 01e36b03e91c..924be8da2888 100644 --- a/src/generators/dom/visitors/MustacheTag.js +++ b/src/generators/dom/visitors/MustacheTag.js @@ -1,20 +1,20 @@ import deindent from '../../../utils/deindent.js'; import findBlock from '../utils/findBlock.js'; -export default function visitMustacheTag ( generator, node ) { - const name = generator.current.getUniqueName( 'text' ); +export default function visitMustacheTag ( generator, fragment, node ) { + const name = fragment.getUniqueName( 'text' ); - const { snippet } = generator.contextualise( node.expression ); + const { snippet } = fragment.contextualise( node.expression ); - generator.current.builders.init.addLine( `var last_${name} = ${snippet};` ); + fragment.create.addLine( `var last_${name} = ${snippet};` ); generator.addElement( name, `${generator.helper( 'createText' )}( last_${name} )`, true ); - const fragment = findBlock( generator.current ); - if ( !fragment.tmp ) fragment.tmp = fragment.getUniqueName( 'tmp' ); + const parentFragment = findBlock( fragment ); + if ( !parentFragment.tmp ) parentFragment.tmp = parentFragment.getUniqueName( 'tmp' ); - generator.current.builders.update.addBlock( deindent` - if ( ( ${fragment.tmp} = ${snippet} ) !== last_${name} ) { - ${name}.data = last_${name} = ${fragment.tmp}; + fragment.builders.update.addBlock( deindent` + if ( ( ${parentFragment.tmp} = ${snippet} ) !== last_${name} ) { + ${name}.data = last_${name} = ${parentFragment.tmp}; } ` ); } \ No newline at end of file diff --git a/src/generators/dom/visitors/RawMustacheTag.js b/src/generators/dom/visitors/RawMustacheTag.js index db87960e7db6..b7b9d9866c4e 100644 --- a/src/generators/dom/visitors/RawMustacheTag.js +++ b/src/generators/dom/visitors/RawMustacheTag.js @@ -1,7 +1,7 @@ import deindent from '../../../utils/deindent.js'; import findBlock from '../utils/findBlock.js'; -export default function visitRawMustacheTag ( generator, node ) { +export default function visitRawMustacheTag ( generator, fragment, node ) { const name = generator.current.getUniqueName( 'raw' ); const { snippet } = generator.contextualise( node.expression ); @@ -26,12 +26,12 @@ export default function visitRawMustacheTag ( generator, node ) { generator.current.builders.init.addLine( mountStatement ); } - const fragment = findBlock( generator.current ); - if ( !fragment.tmp ) fragment.tmp = fragment.getUniqueName( 'tmp' ); + const parentFragment = findBlock( generator.current ); + if ( !parentFragment.tmp ) parentFragment.tmp = parentFragment.getUniqueName( 'tmp' ); generator.current.builders.update.addBlock( deindent` - if ( ( ${fragment.tmp} = ${snippet} ) !== last_${name} ) { - last_${name} = ${fragment.tmp}; + if ( ( ${parentFragment.tmp} = ${snippet} ) !== last_${name} ) { + last_${name} = ${parentFragment.tmp}; ${detachStatement} ${mountStatement} } diff --git a/src/generators/dom/visitors/Text.js b/src/generators/dom/visitors/Text.js index 86231112c4f4..66c3a4c32b2a 100644 --- a/src/generators/dom/visitors/Text.js +++ b/src/generators/dom/visitors/Text.js @@ -1,8 +1,8 @@ -export default function visitText ( generator, node ) { - if ( generator.current.namespace && !/\S/.test( node.data ) ) { +export default function visitText ( generator, fragment, node ) { + if ( fragment.namespace && !/\S/.test( node.data ) ) { return; } - const name = generator.current.getUniqueName( `text` ); + const name = fragment.getUniqueName( `text` ); generator.addElement( name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, false ); } \ No newline at end of file diff --git a/src/generators/dom/visitors/YieldTag.js b/src/generators/dom/visitors/YieldTag.js index 45f28172b20f..d8c2b81490c9 100644 --- a/src/generators/dom/visitors/YieldTag.js +++ b/src/generators/dom/visitors/YieldTag.js @@ -1,4 +1,4 @@ -export default function visitYieldTag ( generator ) { +export default function visitYieldTag ( generator, fragment, node ) { const anchor = `yield_anchor`; generator.createAnchor( anchor ); diff --git a/src/generators/dom/visitors/attributes/addElementAttributes.js b/src/generators/dom/visitors/attributes/addElementAttributes.js index 2d96cc73bf44..163f3d355db1 100644 --- a/src/generators/dom/visitors/attributes/addElementAttributes.js +++ b/src/generators/dom/visitors/attributes/addElementAttributes.js @@ -5,12 +5,12 @@ import flattenReference from '../../../../utils/flattenReference.js'; import getStaticAttributeValue from './binding/getStaticAttributeValue.js'; import findBlock from '../../utils/findBlock.js'; -export default function addElementAttributes ( generator, node, local ) { +export default function addElementAttributes ( generator, element, node ) { node.attributes.forEach( attribute => { const name = attribute.name; if ( attribute.type === 'Attribute' ) { - let metadata = local.namespace ? null : attributeLookup[ name ]; + let metadata = element.namespace ? null : attributeLookup[ name ]; if ( metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) metadata = null; let dynamic = false; @@ -32,29 +32,29 @@ export default function addElementAttributes ( generator, node, local ) { if ( attribute.value === true ) { // attributes without values, e.g.