From d0752cd6b1cd2e112472f165519fe0345ceda8e0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 6 Apr 2017 18:30:43 -0400 Subject: [PATCH] another half-done commit --- src/generators/dom/Fragment.js | 30 +++++++ src/generators/dom/index.js | 32 +------ src/generators/dom/visit.js | 4 +- src/generators/dom/visitors/Component.js | 51 ++++++----- src/generators/dom/visitors/EachBlock.js | 88 +++++++++---------- src/generators/dom/visitors/Element.js | 42 ++++----- src/generators/dom/visitors/IfBlock.js | 28 +++--- src/generators/dom/visitors/MustacheTag.js | 19 ++-- src/generators/dom/visitors/RawMustacheTag.js | 29 +++--- src/generators/dom/visitors/Text.js | 8 +- src/generators/dom/visitors/YieldTag.js | 12 +-- .../attributes/addComponentAttributes.js | 16 ++-- .../attributes/addComponentBinding.js | 14 +-- .../attributes/addElementAttributes.js | 36 ++++---- .../visitors/attributes/addElementBinding.js | 26 +++--- .../visitors/attributes/binding/getSetter.js | 16 ++-- .../attributes/getStaticAttributeValue.js | 0 src/generators/dom/visitors/meta/Window.js | 14 +-- 18 files changed, 234 insertions(+), 231 deletions(-) delete mode 100644 src/generators/dom/visitors/attributes/getStaticAttributeValue.js diff --git a/src/generators/dom/Fragment.js b/src/generators/dom/Fragment.js index 870ac26cac..16b3093d3e 100644 --- a/src/generators/dom/Fragment.js +++ b/src/generators/dom/Fragment.js @@ -3,7 +3,37 @@ export default class Fragment { Object.assign( this, options ); } + addElement ( name, renderStatement, needsIdentifier = false ) { + const isToplevel = this.localElementDepth === 0; + if ( needsIdentifier || isToplevel ) { + this.builders.create.addLine( + `var ${name} = ${renderStatement};` + ); + + this.createMountStatement( name ); + } else { + this.builders.create.addLine( `${this.generator.helper( 'appendNode' )}( ${renderStatement}, ${this.target} );` ); + } + + if ( isToplevel ) { + this.builders.detach.addLine( `${this.generator.helper( 'detachNode' )}( ${name} );` ); + } + } + child ( options ) { return new Fragment( Object.assign( {}, this, options, { parent: this } ) ); } + + createAnchor ( name ) { + const renderStatement = `${this.generator.helper( 'createComment' )}()`; + this.addElement( name, renderStatement, true ); + } + + createMountStatement ( name ) { + if ( this.target === 'target' ) { + this.builders.mount.addLine( `${this.generator.helper( 'insertNode' )}( ${name}, target, anchor );` ); + } else { + this.builders.create.addLine( `${this.generator.helper( 'appendNode' )}( ${name}, ${this.target} );` ); + } + } } \ No newline at end of file diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index c3a97f7482..fb968c1263 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -18,23 +18,6 @@ class DomGenerator extends Generator { }; } - addElement ( name, renderStatement, needsIdentifier = false ) { - const isToplevel = this.current.localElementDepth === 0; - if ( needsIdentifier || isToplevel ) { - this.current.builders.create.addLine( - `var ${name} = ${renderStatement};` - ); - - this.createMountStatement( name ); - } else { - this.current.builders.create.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.create.addLine( `${fragment.autofocus}.focus();` ); @@ -103,19 +86,6 @@ class DomGenerator extends Generator { ` ); } - 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.create.addLine( `${this.helper( 'appendNode' )}( ${name}, ${this.current.target} );` ); - } - } - generateBlock ( node, name, type ) { const childFragment = this.current.child({ type, @@ -183,7 +153,7 @@ export default function dom ( parsed, source, options ) { generator.push( mainFragment ); parsed.html.children.forEach( node => { - visit( node, generator ); + visit( generator, mainFragment, node ); }); generator.addRenderer( mainFragment ); diff --git a/src/generators/dom/visit.js b/src/generators/dom/visit.js index e9837098c4..1b96ed510b 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 8ab6e8da95..623332a334 100644 --- a/src/generators/dom/visitors/Component.js +++ b/src/generators/dom/visitors/Component.js @@ -19,14 +19,13 @@ 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 ) ); + const name = fragment.getUniqueName( capDown( node.name === ':Self' ? generator.name : node.name ) ); const local = { name, - namespace: current.namespace, + namespace: fragment.namespace, isComponent: true, allUsedContexts: [], @@ -35,18 +34,18 @@ export default function visitComponent ( generator, node ) { update: new CodeBuilder() }; - const isToplevel = current.localElementDepth === 0; + const isToplevel = fragment.localElementDepth === 0; generator.hasComponents = true; - addComponentAttributes( generator, node, local ); + addComponentAttributes( generator, fragment, node, local ); if ( local.allUsedContexts.length ) { const initialProps = local.allUsedContexts.map( contextName => { if ( contextName === 'root' ) return `root: root`; - const listName = current.listNames.get( contextName ); - const indexName = current.indexNames.get( contextName ); + const listName = fragment.listNames.get( contextName ); + const indexName = fragment.indexNames.get( contextName ); return `${listName}: ${listName},\n${indexName}: ${indexName}`; }).join( ',\n' ); @@ -54,8 +53,8 @@ export default function visitComponent ( generator, node ) { const updates = local.allUsedContexts.map( contextName => { if ( contextName === 'root' ) return `${name}._context.root = root;`; - const listName = current.listNames.get( contextName ); - const indexName = current.indexNames.get( contextName ); + const listName = fragment.listNames.get( contextName ); + const indexName = fragment.indexNames.get( contextName ); return `${name}._context.${listName} = ${listName};\n${name}._context.${indexName} = ${indexName};`; }).join( '\n' ); @@ -70,24 +69,24 @@ export default function visitComponent ( generator, node ) { } const componentInitProperties = [ - `target: ${!isToplevel ? current.target: 'null'}`, - `_root: ${current.component}._root || ${current.component}` + `target: ${!isToplevel ? fragment.target: 'null'}`, + `_root: ${fragment.component}._root || ${fragment.component}` ]; // Component has children, put them in a separate {{yield}} block if ( hasChildren ) { const yieldName = generator.getUniqueName( `render_${name}_yield_fragment` ); - const params = current.params.join( ', ' ); + const params = fragment.params.join( ', ' ); generator.generateBlock( node, yieldName, 'block' ); - const yieldFragment = current.getUniqueName( `${name}_yield_fragment` ); + const yieldFragment = fragment.getUniqueName( `${name}_yield_fragment` ); - current.builders.create.addLine( - `var ${yieldFragment} = ${yieldName}( ${params}, ${current.component} );` + fragment.builders.create.addLine( + `var ${yieldFragment} = ${yieldName}( ${params}, ${fragment.component} );` ); - current.builders.update.addLine( + fragment.builders.update.addLine( `${yieldFragment}.update( changed, ${params} );` ); @@ -104,7 +103,7 @@ export default function visitComponent ( generator, node ) { const initialPropString = stringifyProps( initialProps ); if ( local.bindings.length ) { - const initialData = current.getUniqueName( `${name}_initial_data` ); + const initialData = fragment.getUniqueName( `${name}_initial_data` ); statements.push( `var ${name}_initial_data = ${initialPropString};` ); @@ -128,7 +127,7 @@ export default function visitComponent ( generator, node ) { ` ); if ( isToplevel ) { - current.builders.mount.addLine( `${name}._fragment.mount( target, anchor );` ); + fragment.builders.mount.addLine( `${name}._fragment.mount( target, anchor );` ); } if ( local.dynamicAttributes.length ) { @@ -153,17 +152,17 @@ export default function visitComponent ( generator, node ) { ` ); } - current.builders.destroy.addLine( `${name}.destroy( ${isToplevel ? 'detach' : 'false'} );` ); + fragment.builders.destroy.addLine( `${name}.destroy( ${isToplevel ? 'detach' : 'false'} );` ); - current.builders.create.addBlock( local.create ); - if ( !local.update.isEmpty() ) current.builders.update.addBlock( local.update ); + fragment.builders.create.addBlock( local.create ); + if ( !local.update.isEmpty() ) fragment.builders.update.addBlock( local.update ); - const childFragment = generator.current.child({ + const childFragment = fragment.child({ type: 'component', namespace: local.namespace, target: name, - parent: current, - localElementDepth: current.localElementDepth + 1, + parent: fragment, + localElementDepth: fragment.localElementDepth + 1, key: null }); generator.push( childFragment ); @@ -171,7 +170,7 @@ export default function visitComponent ( generator, node ) { generator.elementDepth += 1; node.children.forEach( child => { - visit( child, generator ); + visit( generator, childFragment, child ); }); generator.elementDepth -= 1; diff --git a/src/generators/dom/visitors/EachBlock.js b/src/generators/dom/visitors/EachBlock.js index 63aac0000d..369b597048 100644 --- a/src/generators/dom/visitors/EachBlock.js +++ b/src/generators/dom/visitors/EachBlock.js @@ -3,52 +3,52 @@ 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` ); const renderElse = generator.getUniqueName( `${renderer}_else` ); - const i = generator.current.getUniqueName( `i` ); - const params = generator.current.params.join( ', ' ); + const i = fragment.getUniqueName( `i` ); + const params = fragment.params.join( ', ' ); - const listName = generator.current.getUniqueName( `${name}_value` ); + const listName = fragment.getUniqueName( `${name}_value` ); - const isToplevel = generator.current.localElementDepth === 0; + const isToplevel = fragment.localElementDepth === 0; generator.addSourcemapLocations( node.expression ); const { dependencies, snippet } = generator.contextualise( node.expression ); - const anchor = generator.current.getUniqueName( `${name}_anchor` ); - generator.createAnchor( anchor ); + const anchor = fragment.getUniqueName( `${name}_anchor` ); + fragment.createAnchor( anchor ); const localVars = {}; - localVars.iteration = generator.current.getUniqueName( `${name}_iteration` ); - localVars.iterations = generator.current.getUniqueName( `${name}_iterations` ); - localVars._iterations = generator.current.getUniqueName( `_${name}_iterations` ); - localVars.lookup = generator.current.getUniqueName( `${name}_lookup` ); - localVars._lookup = generator.current.getUniqueName( `_${name}_lookup` ); + localVars.iteration = fragment.getUniqueName( `${name}_iteration` ); + localVars.iterations = fragment.getUniqueName( `${name}_iterations` ); + localVars._iterations = fragment.getUniqueName( `_${name}_iterations` ); + localVars.lookup = fragment.getUniqueName( `${name}_lookup` ); + localVars._lookup = fragment.getUniqueName( `_${name}_lookup` ); - generator.current.builders.create.addLine( `var ${listName} = ${snippet};` ); - generator.current.builders.create.addLine( `var ${localVars.iterations} = [];` ); - if ( node.key ) generator.current.builders.create.addLine( `var ${localVars.lookup} = Object.create( null );` ); - if ( node.else ) generator.current.builders.create.addLine( `var ${elseName} = null;` ); + fragment.builders.create.addLine( `var ${listName} = ${snippet};` ); + fragment.builders.create.addLine( `var ${localVars.iterations} = [];` ); + if ( node.key ) fragment.builders.create.addLine( `var ${localVars.lookup} = Object.create( null );` ); + if ( node.else ) fragment.builders.create.addLine( `var ${elseName} = null;` ); const initialRender = new CodeBuilder(); if ( node.key ) { - localVars.fragment = generator.current.getUniqueName( 'fragment' ); - localVars.value = generator.current.getUniqueName( 'value' ); - localVars.key = generator.current.getUniqueName( 'key' ); + localVars.fragment = fragment.getUniqueName( 'fragment' ); + localVars.value = fragment.getUniqueName( 'value' ); + localVars.key = fragment.getUniqueName( 'key' ); initialRender.addBlock( deindent` var ${localVars.key} = ${listName}[${i}].${node.key}; - ${localVars.iterations}[${i}] = ${localVars.lookup}[ ${localVars.key} ] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${generator.current.component}${node.key ? `, ${localVars.key}` : `` } ); + ${localVars.iterations}[${i}] = ${localVars.lookup}[ ${localVars.key} ] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${fragment.component}${node.key ? `, ${localVars.key}` : `` } ); ` ); } else { initialRender.addLine( - `${localVars.iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${generator.current.component} );` + `${localVars.iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${fragment.component} );` ); } @@ -58,29 +58,29 @@ export default function visitEachBlock ( generator, node ) { ); } - generator.current.builders.create.addBlock( deindent` + fragment.builders.create.addBlock( deindent` for ( var ${i} = 0; ${i} < ${listName}.length; ${i} += 1 ) { ${initialRender} } ` ); if ( node.else ) { - generator.current.builders.create.addBlock( deindent` + fragment.builders.create.addBlock( deindent` if ( !${listName}.length ) { - ${elseName} = ${renderElse}( ${params}, ${generator.current.component} ); + ${elseName} = ${renderElse}( ${params}, ${fragment.component} ); ${!isToplevel ? `${elseName}.mount( ${anchor}.parentNode, ${anchor} );` : ''} } ` ); } if ( isToplevel ) { - generator.current.builders.mount.addBlock( deindent` + fragment.builders.mount.addBlock( deindent` for ( var ${i} = 0; ${i} < ${localVars.iterations}.length; ${i} += 1 ) { ${localVars.iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} ); } ` ); if ( node.else ) { - generator.current.builders.mount.addBlock( deindent` + fragment.builders.mount.addBlock( deindent` if ( ${elseName} ) { ${elseName}.mount( ${anchor}.parentNode, ${anchor} ); } @@ -89,7 +89,7 @@ export default function visitEachBlock ( generator, node ) { } if ( node.key ) { - generator.current.builders.update.addBlock( deindent` + fragment.builders.update.addBlock( deindent` var ${listName} = ${snippet}; var ${localVars._iterations} = []; var ${localVars._lookup} = Object.create( null ); @@ -105,7 +105,7 @@ export default function visitEachBlock ( generator, node ) { ${localVars._iterations}[${i}] = ${localVars._lookup}[ ${localVars.key} ] = ${localVars.lookup}[ ${localVars.key} ]; ${localVars._lookup}[ ${localVars.key} ].update( changed, ${params}, ${listName}, ${listName}[${i}], ${i} ); } else { - ${localVars._iterations}[${i}] = ${localVars._lookup}[ ${localVars.key} ] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${generator.current.component}${node.key ? `, ${localVars.key}` : `` } ); + ${localVars._iterations}[${i}] = ${localVars._lookup}[ ${localVars.key} ] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${fragment.component}${node.key ? `, ${localVars.key}` : `` } ); } ${localVars._iterations}[${i}].mount( ${localVars.fragment}, null ); @@ -125,12 +125,12 @@ export default function visitEachBlock ( generator, node ) { ${localVars.lookup} = ${localVars._lookup}; ` ); } else { - generator.current.builders.update.addBlock( deindent` + fragment.builders.update.addBlock( deindent` var ${listName} = ${snippet}; for ( var ${i} = 0; ${i} < ${listName}.length; ${i} += 1 ) { if ( !${localVars.iterations}[${i}] ) { - ${localVars.iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${generator.current.component} ); + ${localVars.iterations}[${i}] = ${renderer}( ${params}, ${listName}, ${listName}[${i}], ${i}, ${fragment.component} ); ${localVars.iterations}[${i}].mount( ${anchor}.parentNode, ${anchor} ); } else { ${localVars.iterations}[${i}].update( changed, ${params}, ${listName}, ${listName}[${i}], ${i} ); @@ -144,11 +144,11 @@ export default function visitEachBlock ( generator, node ) { } if ( node.else ) { - generator.current.builders.update.addBlock( deindent` + fragment.builders.update.addBlock( deindent` if ( !${listName}.length && ${elseName} ) { ${elseName}.update( changed, ${params} ); } else if ( !${listName}.length ) { - ${elseName} = ${renderElse}( ${params}, ${generator.current.component} ); + ${elseName} = ${renderElse}( ${params}, ${fragment.component} ); ${elseName}.mount( ${anchor}.parentNode, ${anchor} ); } else if ( ${elseName} ) { ${elseName}.destroy( true ); @@ -156,11 +156,11 @@ export default function visitEachBlock ( generator, node ) { ` ); } - generator.current.builders.destroy.addBlock( + fragment.builders.destroy.addBlock( `${generator.helper( 'destroyEach' )}( ${localVars.iterations}, ${isToplevel ? 'detach' : 'false'} );` ); if ( node.else ) { - generator.current.builders.destroy.addBlock( deindent` + fragment.builders.destroy.addBlock( deindent` if ( ${elseName} ) { ${elseName}.destroy( ${isToplevel ? 'detach' : 'false'} ); } @@ -171,28 +171,28 @@ export default function visitEachBlock ( generator, node ) { generator.generateBlock( node.else, renderElse, 'block' ); } - const indexNames = new Map( generator.current.indexNames ); - const indexName = node.index || generator.current.getUniqueName( `${node.context}_index` ); + const indexNames = new Map( fragment.indexNames ); + const indexName = node.index || fragment.getUniqueName( `${node.context}_index` ); indexNames.set( node.context, indexName ); - const listNames = new Map( generator.current.listNames ); + const listNames = new Map( fragment.listNames ); listNames.set( node.context, listName ); const context = generator.getUniqueName( node.context ); - const contexts = new Map( generator.current.contexts ); + const contexts = new Map( fragment.contexts ); contexts.set( node.context, context ); - const indexes = new Map( generator.current.indexes ); + const indexes = new Map( fragment.indexes ); if ( node.index ) indexes.set( indexName, node.context ); - const contextDependencies = new Map( generator.current.contextDependencies ); + const contextDependencies = new Map( fragment.contextDependencies ); contextDependencies.set( node.context, dependencies ); - const blockParams = generator.current.params.concat( listName, context, indexName ); + const blockParams = fragment.params.concat( listName, context, indexName ); const getUniqueName = generator.getUniqueNameMaker( blockParams ); - const childFragment = generator.current.child({ + const childFragment = fragment.child({ type: 'block', name: renderer, target: 'target', @@ -218,9 +218,9 @@ export default function visitEachBlock ( generator, node ) { generator.push( childFragment ); node.children.forEach( child => { - visit( child, generator ); + visit( generator, childFragment, child ); }); - generator.addRenderer( generator.current ); + generator.addRenderer( childFragment ); generator.pop(); } \ No newline at end of file diff --git a/src/generators/dom/visitors/Element.js b/src/generators/dom/visitors/Element.js index 95b55a12bb..4db5bf32f2 100644 --- a/src/generators/dom/visitors/Element.js +++ b/src/generators/dom/visitors/Element.js @@ -9,20 +9,20 @@ 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 ); + return meta[ node.name ]( generator, fragment, node ); } if ( generator.components.has( node.name ) || node.name === ':Self' ) { - return visitComponent( generator, node ); + return visitComponent( generator, fragment, node ); } - const name = generator.current.getUniqueName( node.name ); + const name = fragment.getUniqueName( node.name ); const local = { name, - namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : generator.current.namespace, + namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : fragment.namespace, isComponent: false, allUsedContexts: [], @@ -32,16 +32,16 @@ export default function visitElement ( generator, node ) { destroy: new CodeBuilder() }; - const isToplevel = generator.current.localElementDepth === 0; + const isToplevel = fragment.localElementDepth === 0; - addElementAttributes( generator, node, local ); + addElementAttributes( generator, fragment, node, local ); 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 = fragment.listNames.get( contextName ); + const indexName = fragment.indexNames.get( contextName ); return `${listName}: ${listName},\n${indexName}: ${indexName}`; }).join( ',\n' ); @@ -49,8 +49,8 @@ export default function visitElement ( generator, node ) { 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 = fragment.listNames.get( contextName ); + const indexName = fragment.indexNames.get( contextName ); return `${name}.__svelte.${listName} = ${listName};\n${name}.__svelte.${indexName} = ${indexName};`; }).join( '\n' ); @@ -82,7 +82,7 @@ export default function visitElement ( generator, node ) { local.create.addLineAtStart( render ); if ( isToplevel ) { - generator.current.builders.detach.addLine( `${generator.helper( 'detachNode' )}( ${name} );` ); + fragment.builders.detach.addLine( `${generator.helper( 'detachNode' )}( ${name} );` ); } // special case – bound