use builders for local.init and local.update

pull/183/head
Rich-Harris 9 years ago
parent 2d35f937a9
commit 3e57814b76

@ -1,4 +1,5 @@
import deindent from '../../utils/deindent.js';
import CodeBuilder from '../../utils/CodeBuilder.js';
import addComponentAttributes from './attributes/addComponentAttributes.js';
export default {
@ -13,11 +14,8 @@ export default {
allUsedContexts: new Set(),
init: [],
mount: [],
update: [],
detach: [],
teardown: []
init: new CodeBuilder(),
update: new CodeBuilder()
};
const isToplevel = generator.current.localElementDepth === 0;
@ -77,7 +75,7 @@ export default {
componentInitProperties.push(`data: ${name}_initialData`);
}
local.init.unshift( deindent`
local.init.addBlockAtStart( deindent`
${statements.join( '\n\n' )}
var ${name} = new template.components.${node.name}({
${componentInitProperties.join(',\n')}
@ -101,7 +99,7 @@ export default {
return `${name}_changes.${attribute.name} = ${attribute.value};`;
});
local.update.push( deindent`
local.update.addBlock( deindent`
var ${name}_changes = {};
${updates.join( '\n' )}
@ -112,8 +110,8 @@ export default {
generator.current.builders.teardown.addLine( `${name}.teardown( ${isToplevel ? 'detach' : 'false'} );` );
generator.current.builders.init.addBlock( local.init.join( '\n' ) );
if ( local.update.length ) generator.current.builders.update.addBlock( local.update.join( '\n' ) );
generator.current.builders.init.addBlock( local.init );
if ( !local.update.isEmpty() ) generator.current.builders.update.addBlock( local.update );
generator.push({
namespace: local.namespace,

@ -1,3 +1,4 @@
import CodeBuilder from '../../utils/CodeBuilder.js';
import deindent from '../../utils/deindent.js';
import addElementAttributes from './attributes/addElementAttributes.js';
import Component from './Component.js';
@ -18,11 +19,8 @@ export default {
allUsedContexts: new Set(),
init: [],
mount: [],
update: [],
detach: [],
teardown: []
init: new CodeBuilder(),
update: new CodeBuilder()
};
const isToplevel = generator.current.localElementDepth === 0;
@ -50,13 +48,13 @@ export default {
return `${name}.__svelte.${listName} = ${listName};\n${name}.__svelte.${indexName} = ${indexName};`;
}).join( '\n' );
local.init.push( deindent`
local.init.addBlock( deindent`
${name}.__svelte = {
${initialProps}
};
` );
local.update.push( updates );
local.update.addBlock( updates );
}
let render = local.namespace ?
@ -67,7 +65,7 @@ export default {
render += `\n${name}.setAttribute( '${generator.cssId}', '' );`;
}
local.init.unshift( render );
local.init.addLineAtStart( render );
if ( isToplevel ) {
generator.current.builders.detach.addLine( `${name}.parentNode.removeChild( ${name} );` );
}
@ -76,11 +74,13 @@ export default {
if ( node.name === 'option' && !node.attributes.find( attribute => attribute.type === 'Attribute' && attribute.name === 'value' ) ) { // TODO check it's bound
// const dynamic = node.children.length > 1 || node.children[0].type !== 'Text';
// TODO do this in init for static values... have to do it in `leave`, because they don't exist yet
local.update.push( `${name}.__value = ${name}.textContent` );
local.update.addLine(
`${name}.__value = ${name}.textContent`
);
}
generator.current.builders.init.addBlock( local.init.join( '\n' ) );
if ( local.update.length ) generator.current.builders.update.addBlock( local.update.join( '\n' ) );
generator.current.builders.init.addBlock( local.init );
if ( !local.update.isEmpty() ) generator.current.builders.update.addBlock( local.update );
generator.createMountStatement( name );

@ -104,7 +104,7 @@ export default function addComponentAttributes ( generator, node, local ) {
const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
local.init.push( deindent`
local.init.addBlock( deindent`
${local.name}.on( '${attribute.name}', function ( event ) {
${handlerBody}
});
@ -118,9 +118,9 @@ export default function addComponentAttributes ( generator, node, local ) {
else if ( attribute.type === 'Ref' ) {
generator.usesRefs = true;
local.init.push( deindent`
component.refs.${attribute.name} = ${local.name};
` );
local.init.addLine(
`component.refs.${attribute.name} = ${local.name};`
);
generator.current.builders.teardown.addLine( deindent`
if ( component.refs.${attribute.name} === ${local.name} ) component.refs.${attribute.name} = null;

@ -17,13 +17,13 @@ export default function addElementAttributes ( generator, node, local ) {
if ( attribute.value === true ) {
// attributes without values, e.g. <textarea readonly>
if ( propertyName ) {
local.init.push( deindent`
${local.name}.${propertyName} = true;
` );
local.init.addLine(
`${local.name}.${propertyName} = true;`
);
} else {
local.init.push( deindent`
${local.name}.setAttribute( '${attribute.name}', true );
` );
local.init.addLine(
`${local.name}.setAttribute( '${attribute.name}', true );`
);
}
// special case autofocus. has to be handled in a bit of a weird way
@ -34,13 +34,13 @@ export default function addElementAttributes ( generator, node, local ) {
else if ( attribute.value.length === 0 ) {
if ( propertyName ) {
local.init.push( deindent`
${local.name}.${propertyName} = '';
` );
local.init.addLine(
`${local.name}.${propertyName} = '';`
);
} else {
local.init.push( deindent`
${local.name}.setAttribute( '${attribute.name}', '' );
` );
local.init.addLine(
`${local.name}.setAttribute( '${attribute.name}', '' );`
);
}
}
@ -58,13 +58,13 @@ export default function addElementAttributes ( generator, node, local ) {
// TODO this attribute must be static enforce at compile time
local.namespace = value.data;
} else if ( propertyName ) {
local.init.push( deindent`
${local.name}.${propertyName} = ${result};
` );
local.init.addLine(
`${local.name}.${propertyName} = ${result};`
);
} else {
local.init.push( deindent`
${local.name}.setAttribute( '${attribute.name}', ${result} );
` );
local.init.addLine(
`${local.name}.setAttribute( '${attribute.name}', ${result} );`
);
}
}
@ -78,8 +78,8 @@ export default function addElementAttributes ( generator, node, local ) {
`${local.name}.${propertyName} = ${snippet};` :
`${local.name}.setAttribute( '${attribute.name}', ${snippet} );`; // TODO use snippet both times see note below
local.init.push( updater );
local.update.push( updater );
local.init.addLine( updater );
local.update.addLine( updater );
}
}
@ -103,12 +103,12 @@ export default function addElementAttributes ( generator, node, local ) {
`${local.name}.${propertyName} = ${value};` :
`${local.name}.setAttribute( '${attribute.name}', ${value} );`;
local.init.push( updater );
local.update.push( updater );
local.init.addLine( updater );
local.update.addLine( updater );
}
if ( isBoundOptionValue ) {
( dynamic ? local.update : local.init ).push( `${local.name}.value = ${local.name}.__value` );
( dynamic ? local.update : local.init ).addLine( `${local.name}.value = ${local.name}.__value` );
}
}
@ -146,7 +146,7 @@ export default function addElementAttributes ( generator, node, local ) {
const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
if ( attribute.name in generator.events ) {
local.init.push( deindent`
local.init.addBlock( deindent`
var ${handlerName} = template.events.${attribute.name}.call( component, ${local.name}, function ( event ) {
${handlerBody}
});
@ -156,7 +156,7 @@ export default function addElementAttributes ( generator, node, local ) {
${handlerName}.teardown();
` );
} else {
local.init.push( deindent`
local.init.addBlock( deindent`
function ${handlerName} ( event ) {
${handlerBody}
}
@ -177,9 +177,9 @@ export default function addElementAttributes ( generator, node, local ) {
else if ( attribute.type === 'Ref' ) {
generator.usesRefs = true;
local.init.push( deindent`
component.refs.${attribute.name} = ${local.name};
` );
local.init.addLine(
`component.refs.${attribute.name} = ${local.name};`
);
generator.current.builders.teardown.addLine( deindent`
if ( component.refs.${attribute.name} === ${local.name} ) component.refs.${attribute.name} = null;

@ -84,7 +84,7 @@ export default function createBinding ( generator, node, attribute, current, loc
if ( local.isComponent ) {
generator.hasComplexBindings = true;
local.init.push( deindent`
local.init.addBlock( deindent`
var ${local.name}_updating = false;
component.__bindings.push( function () {
@ -96,7 +96,7 @@ export default function createBinding ( generator, node, attribute, current, loc
});
` );
local.update.push( deindent`
local.update.addBlock( deindent`
if ( !${local.name}_updating && '${parts[0]}' in changed ) {
${local.name}.set({ ${attribute.name}: ${contextual ? attribute.value : `root.${attribute.value}`} });
}
@ -104,7 +104,7 @@ export default function createBinding ( generator, node, attribute, current, loc
} else {
const updateElement = `${local.name}.${attribute.name} = ${contextual ? attribute.value : `root.${attribute.value}`}`;
local.init.push( deindent`
local.init.addBlock( deindent`
var ${local.name}_updating = false;
function ${handler} () {
@ -117,9 +117,9 @@ export default function createBinding ( generator, node, attribute, current, loc
${updateElement};
` );
local.update.push( deindent`
if ( !${local.name}_updating ) ${updateElement};
` );
local.update.addLine(
`if ( !${local.name}_updating ) ${updateElement};`
);
generator.current.builders.teardown.addLine( deindent`
${local.name}.removeEventListener( '${eventName}', ${handler}, false );
@ -128,6 +128,6 @@ export default function createBinding ( generator, node, attribute, current, loc
if ( node.name === 'select' ) {
generator.hasComplexBindings = true;
local.init.push( `component.__bindings.push( ${handler} )` );
local.init.addLine( `component.__bindings.push( ${handler} )` );
}
}

@ -4,6 +4,8 @@ const BLOCK = {};
export default class CodeBuilder {
constructor () {
this.result = '';
this.first = null;
this.last = null;
}
@ -17,12 +19,28 @@ export default class CodeBuilder {
this.last = LINE;
}
addLineAtStart ( line ) {
if ( this.first === BLOCK ) {
this.result = `${line}\n\n${this.result}`;
} else {
this.result = `${line}\n${this.result}`;
}
this.first = LINE;
}
addBlock ( block ) {
this.result += `\n\n${block}`;
this.last = BLOCK;
}
addBlockAtStart ( block ) {
this.result = `${block}\n\n${this.result}`;
this.first = BLOCK;
}
isEmpty () {
return this.result === '';
}

Loading…
Cancel
Save