From b75bb294086007216e45229bdd0a5a8f9735ddd1 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Sun, 4 Dec 2016 17:31:02 +0100 Subject: [PATCH] move component codegen into its own file --- compiler/generate/visitors/Component.js | 111 ++++++++++++++++ compiler/generate/visitors/Element.js | 162 +++++++----------------- 2 files changed, 156 insertions(+), 117 deletions(-) create mode 100644 compiler/generate/visitors/Component.js diff --git a/compiler/generate/visitors/Component.js b/compiler/generate/visitors/Component.js new file mode 100644 index 0000000000..77dc13bc83 --- /dev/null +++ b/compiler/generate/visitors/Component.js @@ -0,0 +1,111 @@ +import deindent from '../utils/deindent.js'; +import addComponentAttributes from './attributes/addComponentAttributes.js'; + +export default { + enter ( generator, node ) { + const name = generator.current.counter( `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` ); + + const local = { + name, + namespace: generator.current.namespace, + isComponent: true, + + allUsedContexts: new Set(), + + init: [], + mount: [], + update: [], + teardown: [] + }; + + const isToplevel = generator.current.localElementDepth === 0; + + generator.hasComponents = true; + + addComponentAttributes( generator, node, local ); + + if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) { + const initialProps = local.staticAttributes + .concat( local.dynamicAttributes ) + .map( attribute => `${attribute.name}: ${attribute.value}` ); + + const statements = []; + + if ( initialProps.length ) { + statements.push( deindent` + var ${name}_initialData = { + ${initialProps.join( ',\n' )} + }; + ` ); + } else { + statements.push( `var ${name}_initialData = {};` ); + } + + if ( local.bindings.length ) { + const bindings = local.bindings.map( binding => { + const parts = binding.value.split( '.' ); + const tail = parts.pop(); + return `if ( '${tail}' in ${parts.join( '.' )} ) ${name}_initialData.${binding.name} = ${binding.value};`; + }); + + statements.push( bindings.join( '\n' ) ); + } + + local.init.unshift( deindent` + ${statements.join( '\n\n' )} + + var ${name} = new template.components.${node.name}({ + target: ${!isToplevel ? generator.current.target: 'null'}, + root: component.root || component, + data: ${name}_initialData + }); + ` ); + } else { + local.init.unshift( deindent` + var ${name} = new template.components.${node.name}({ + target: ${!isToplevel ? generator.current.target: 'null'}, + root: component.root || component + }); + ` ); + } + + if ( isToplevel ) { + local.mount.unshift( `${name}.mount( target, anchor );` ); + } + + if ( local.dynamicAttributes.length ) { + const updates = local.dynamicAttributes.map( attribute => { + return deindent` + if ( ${attribute.dependencies.map( dependency => `'${dependency}' in changed` ).join( '||' )} ) ${name}_changes.${attribute.name} = ${attribute.value}; + `; + }); + + local.update.push( deindent` + var ${name}_changes = {}; + + ${updates.join( '\n' )} + + if ( Object.keys( ${name}_changes ).length ) ${name}.set( ${name}_changes ); + ` ); + } + + local.teardown.push( `${name}.teardown( ${isToplevel ? 'detach' : 'false'} );` ); + + generator.current.initStatements.push( local.init.join( '\n' ) ); + if ( local.update.length ) generator.current.updateStatements.push( local.update.join( '\n' ) ); + if ( local.mount.length ) generator.current.mountStatements.push( local.mount.join( '\n' ) ); + generator.current.teardownStatements.push( local.teardown.join( '\n' ) ); + + generator.push({ + namespace: local.namespace, + target: name, + parent: generator.current, + elementDepth: generator.current.elementDepth + 1, + localElementDepth: generator.current.localElementDepth + 1 + }); + }, + + leave ( generator ) { + generator.pop(); + } +}; diff --git a/compiler/generate/visitors/Element.js b/compiler/generate/visitors/Element.js index 7b050cdb1a..265b917ef5 100644 --- a/compiler/generate/visitors/Element.js +++ b/compiler/generate/visitors/Element.js @@ -1,16 +1,20 @@ import deindent from '../utils/deindent.js'; -import addComponentAttributes from './attributes/addComponentAttributes.js'; import addElementAttributes from './attributes/addElementAttributes.js'; +import Component from './Component.js'; export default { enter ( generator, node ) { const isComponent = node.name in generator.components; - const name = generator.current.counter( isComponent ? `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` : node.name ); + if ( isComponent ) { + return Component.enter( generator, node ); + } + + const name = generator.current.counter( node.name ); const local = { name, namespace: name === 'svg' ? 'http://www.w3.org/2000/svg' : generator.current.namespace, - isComponent, + isComponent: false, allUsedContexts: new Set(), @@ -22,124 +26,49 @@ export default { const isToplevel = generator.current.localElementDepth === 0; - if ( isComponent ) { - generator.hasComponents = true; - - addComponentAttributes( generator, node, local ); - - if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) { - const initialProps = local.staticAttributes - .concat( local.dynamicAttributes ) - .map( attribute => `${attribute.name}: ${attribute.value}` ); - - const statements = []; - - if ( initialProps.length ) { - statements.push( deindent` - var ${name}_initialData = { - ${initialProps.join( ',\n' )} - }; - ` ); - } else { - statements.push( `var ${name}_initialData = {};` ); - } - - if ( local.bindings.length ) { - const bindings = local.bindings.map( binding => { - const parts = binding.value.split( '.' ); - const tail = parts.pop(); - return `if ( '${tail}' in ${parts.join( '.' )} ) ${name}_initialData.${binding.name} = ${binding.value};`; - }); - - statements.push( bindings.join( '\n' ) ); - } - - local.init.unshift( deindent` - ${statements.join( '\n\n' )} - - var ${name} = new template.components.${node.name}({ - target: ${!isToplevel ? generator.current.target: 'null'}, - root: component.root || component, - data: ${name}_initialData - }); - ` ); - } else { - local.init.unshift( deindent` - var ${name} = new template.components.${node.name}({ - target: ${!isToplevel ? generator.current.target: 'null'}, - root: component.root || component - }); - ` ); - } - - if ( isToplevel ) { - local.mount.unshift( `${name}.mount( target, anchor );` ); - } - - if ( local.dynamicAttributes.length ) { - const updates = local.dynamicAttributes.map( attribute => { - return deindent` - if ( ${attribute.dependencies.map( dependency => `'${dependency}' in changed` ).join( '||' )} ) ${name}_changes.${attribute.name} = ${attribute.value}; - `; - }); - - local.update.push( deindent` - var ${name}_changes = {}; - - ${updates.join( '\n' )} - - if ( Object.keys( ${name}_changes ).length ) ${name}.set( ${name}_changes ); - ` ); - } - - local.teardown.push( `${name}.teardown( ${isToplevel ? 'detach' : 'false'} );` ); - } - - else { - addElementAttributes( generator, node, local ); + addElementAttributes( generator, node, local ); - if ( local.allUsedContexts.size ) { - const contextNames = [...local.allUsedContexts]; + if ( local.allUsedContexts.size ) { + const contextNames = [...local.allUsedContexts]; - const initialProps = contextNames.map( contextName => { - if ( contextName === 'root' ) return `root: root`; + const initialProps = contextNames.map( contextName => { + if ( contextName === 'root' ) return `root: root`; - const listName = generator.current.listNames[ contextName ]; - const indexName = generator.current.indexNames[ contextName ]; + const listName = generator.current.listNames[ contextName ]; + const indexName = generator.current.indexNames[ contextName ]; - return `${listName}: ${listName},\n${indexName}: ${indexName}`; - }).join( ',\n' ); + return `${listName}: ${listName},\n${indexName}: ${indexName}`; + }).join( ',\n' ); - const updates = contextNames.map( contextName => { - if ( contextName === 'root' ) return `${name}.__svelte.root = root;`; + const updates = contextNames.map( contextName => { + if ( contextName === 'root' ) return `${name}.__svelte.root = root;`; - const listName = generator.current.listNames[ contextName ]; - const indexName = generator.current.indexNames[ contextName ]; + const listName = generator.current.listNames[ contextName ]; + const indexName = generator.current.indexNames[ 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.push( deindent` - ${name}.__svelte = { - ${initialProps} - }; - ` ); + local.init.push( deindent` + ${name}.__svelte = { + ${initialProps} + }; + ` ); - local.update.push( updates ); - } + local.update.push( updates ); + } - let render = local.namespace ? - `var ${name} = document.createElementNS( '${local.namespace}', '${node.name}' );` : - `var ${name} = document.createElement( '${node.name}' );`; + let render = local.namespace ? + `var ${name} = document.createElementNS( '${local.namespace}', '${node.name}' );` : + `var ${name} = document.createElement( '${node.name}' );`; - if ( generator.cssId && !generator.current.elementDepth ) { - render += `\n${name}.setAttribute( '${generator.cssId}', '' );`; - } + if ( generator.cssId && !generator.current.elementDepth ) { + render += `\n${name}.setAttribute( '${generator.cssId}', '' );`; + } - local.init.unshift( render ); - if ( isToplevel ) { - local.teardown.push( `if ( detach ) ${name}.parentNode.removeChild( ${name} );` ); - } + local.init.unshift( render ); + if ( isToplevel ) { + local.teardown.push( `if ( detach ) ${name}.parentNode.removeChild( ${name} );` ); } // special case – bound