Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc fixes #491

Merged
merged 7 commits into from
Apr 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions src/generators/Generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class Generator {
// allow compiler to deconflict user's `import { get } from 'whatever'` and
// Svelte's builtin `import { get, ... } from 'svelte/shared.js'`;
this.importedNames = new Set();
this._aliases = new Map();
this.aliases = new Map();
this._usedNames = new Set( [ name ] );
}

Expand All @@ -54,12 +54,11 @@ export default class Generator {
}

alias ( name ) {
if ( this._aliases.has( name ) ) {
return this._aliases.get( name );
if ( !this.aliases.has( name ) ) {
this.aliases.set( name, this.getUniqueName( name ) );
}
const alias = this.getUniqueName( name );
this._aliases.set( name, alias );
return alias;

return this.aliases.get( name );
}

contextualise ( block, expression, context, isEventHandler ) {
Expand Down Expand Up @@ -151,7 +150,7 @@ export default class Generator {
};
}

findDependencies ( contextDependencies, expression ) {
findDependencies ( contextDependencies, indexes, expression ) {
if ( expression._dependencies ) return expression._dependencies;

let scope = annotateWithScopes( expression );
Expand All @@ -170,7 +169,7 @@ export default class Generator {

if ( contextDependencies.has( name ) ) {
dependencies.push( ...contextDependencies.get( name ) );
} else {
} else if ( !indexes.has( name ) ) {
dependencies.push( name );
}

Expand Down
11 changes: 10 additions & 1 deletion src/generators/dom/Block.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default class Block {
destroy: new CodeBuilder()
};

this.aliases = new Map();
this.getUniqueName = this.generator.getUniqueNameMaker( options.params );

// unique names
Expand Down Expand Up @@ -61,6 +62,14 @@ export default class Block {
}
}

alias ( name ) {
if ( !this.aliases.has( name ) ) {
this.aliases.set( name, this.getUniqueName( name ) );
}

return this.aliases.get( name );
}

child ( options ) {
return new Block( Object.assign( {}, this, options, { parent: this } ) );
}
Expand All @@ -75,7 +84,7 @@ export default class Block {
}

findDependencies ( expression ) {
return this.generator.findDependencies( this.contextDependencies, expression );
return this.generator.findDependencies( this.contextDependencies, this.indexes, expression );
}

mount ( name, parentNode ) {
Expand Down
2 changes: 1 addition & 1 deletion src/generators/dom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function dom ( parsed, source, options ) {

const { computations, hasJs, templateProperties, namespace } = generator.parseJs();

const block = preprocess( generator, parsed.html.children );
const block = preprocess( generator, parsed.html );

const state = {
namespace,
Expand Down
75 changes: 55 additions & 20 deletions src/generators/dom/preprocess.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Block from './Block.js';
import { trimStart, trimEnd } from '../../utils/trim.js';

function isElseIf ( node ) {
return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
Expand All @@ -23,7 +24,7 @@ const preprocessors = {
});

blocks.push( node._block );
preprocessChildren( generator, node._block, node.children );
preprocessChildren( generator, node._block, node );

if ( node._block.dependencies.size > 0 ) {
dynamic = true;
Expand All @@ -38,7 +39,7 @@ const preprocessors = {
});

blocks.push( node.else._block );
preprocessChildren( generator, node.else._block, node.else.children );
preprocessChildren( generator, node.else._block, node.else );

if ( node.else._block.dependencies.size > 0 ) {
dynamic = true;
Expand Down Expand Up @@ -97,7 +98,7 @@ const preprocessors = {
});

generator.blocks.push( node._block );
preprocessChildren( generator, node._block, node.children );
preprocessChildren( generator, node._block, node );
block.addDependencies( node._block.dependencies );
node._block.hasUpdateMethod = node._block.dependencies.size > 0;

Expand All @@ -107,7 +108,7 @@ const preprocessors = {
});

generator.blocks.push( node.else._block );
preprocessChildren( generator, node.else._block, node.else.children );
preprocessChildren( generator, node.else._block, node.else );
node.else._block.hasUpdateMethod = node.else._block.dependencies.size > 0;
}
},
Expand All @@ -131,35 +132,56 @@ const preprocessors = {

const isComponent = generator.components.has( node.name ) || node.name === ':Self';

if ( isComponent ) {
const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );
if ( node.children.length ) {
if ( isComponent ) {
const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );

node._block = block.child({
name: generator.getUniqueName( `create_${name}_yield_fragment` )
});
node._block = block.child({
name: generator.getUniqueName( `create_${name}_yield_fragment` )
});

generator.blocks.push( node._block );
preprocessChildren( generator, node._block, node.children );
block.addDependencies( node._block.dependencies );
node._block.hasUpdateMethod = node._block.dependencies.size > 0;
}
generator.blocks.push( node._block );
preprocessChildren( generator, node._block, node );
block.addDependencies( node._block.dependencies );
node._block.hasUpdateMethod = node._block.dependencies.size > 0;
}

else {
preprocessChildren( generator, block, node.children );
else {
preprocessChildren( generator, block, node );
}
}
}
};

preprocessors.RawMustacheTag = preprocessors.MustacheTag;

function preprocessChildren ( generator, block, children ) {
children.forEach( child => {
function preprocessChildren ( generator, block, node ) {
// glue text nodes together
const cleaned = [];
let lastChild;

node.children.forEach( child => {
if ( child.type === 'Comment' ) return;

if ( child.type === 'Text' && lastChild && lastChild.type === 'Text' ) {
lastChild.data += child.data;
lastChild.end = child.end;
} else {
cleaned.push( child );
}

lastChild = child;
});

node.children = cleaned;

cleaned.forEach( child => {
const preprocess = preprocessors[ child.type ];
if ( preprocess ) preprocess( generator, block, child );
});
}

export default function preprocess ( generator, children ) {
export default function preprocess ( generator, node ) {
const block = new Block({
generator,
name: generator.alias( 'create_main_fragment' ),
Expand All @@ -177,8 +199,21 @@ export default function preprocess ( generator, children ) {
});

generator.blocks.push( block );
preprocessChildren( generator, block, children );
preprocessChildren( generator, block, node );
block.hasUpdateMethod = block.dependencies.size > 0;

// trim leading and trailing whitespace from the top level
const firstChild = node.children[0];
if ( firstChild && firstChild.type === 'Text' ) {
firstChild.data = trimStart( firstChild.data );
if ( !firstChild.data ) node.children.shift();
}

const lastChild = node.children[ node.children.length - 1 ];
if ( lastChild && lastChild.type === 'Text' ) {
lastChild.data = trimEnd( lastChild.data );
if ( !lastChild.data ) node.children.pop();
}

return block;
}
3 changes: 0 additions & 3 deletions src/generators/dom/visitors/Comment.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/generators/dom/visitors/EachBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function visitEachBlock ( generator, block, state, node ) {
const create_each_block = node._block.name;
const each_block_value = node._block.listName;
const iterations = block.getUniqueName( `${each_block}_iterations` );
const i = block.getUniqueName( `i` );
const i = block.alias( `i` );
const params = block.params.join( ', ' );
const anchor = block.getUniqueName( `${each_block}_anchor` );

Expand Down Expand Up @@ -188,7 +188,7 @@ function unkeyed ( generator, block, state, node, snippet, { create_each_block,
` );

const dependencies = block.findDependencies( node.expression );
const allDependencies = new Set( block.dependencies );
const allDependencies = new Set( node._block.dependencies );
dependencies.forEach( dependency => {
allDependencies.add( dependency );
});
Expand Down
71 changes: 62 additions & 9 deletions src/generators/dom/visitors/IfBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,73 @@ function visitChildren ( generator, block, state, node ) {
}

export default function visitIfBlock ( generator, block, state, node ) {
const params = block.params.join( ', ' );
const name = generator.getUniqueName( `if_block` );
const getBlock = block.getUniqueName( `get_block` );
const current_block = block.getUniqueName( `current_block` );
const anchor = generator.getUniqueName( `${name}_anchor` );
const params = block.params.join( ', ' );

const vars = { name, anchor, params };

block.createAnchor( anchor, state.parentNode );

const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) );
const dynamic = branches.some( branch => branch.dynamic );

const anchor = `${name}_anchor`;
block.createAnchor( anchor, state.parentNode );
if ( node.else ) {
compound( generator, block, state, node, branches, dynamic, vars );
} else {
simple( generator, block, state, node, branches[0], dynamic, vars );
}

block.builders.destroy.addLine(
`if ( ${name} ) ${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );`
);
}

function simple ( generator, block, state, node, branch, dynamic, { name, anchor, params } ) {
block.builders.create.addBlock( deindent`
var ${name} = ${branch.condition} && ${branch.block}( ${params}, ${block.component} );
` );

const isToplevel = !state.parentNode;

if ( isToplevel ) {
block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` );
} else {
block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, ${anchor} );` );
}

if ( dynamic ) {
block.builders.update.addBlock( deindent`
if ( ${branch.condition} ) {
if ( ${name} ) {
${name}.update( changed, ${params} );
} else {
${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} );
}
} else if ( ${name} ) {
${name}.destroy( true );
${name} = null;
}
` );
} else {
block.builders.update.addBlock( deindent`
if ( ${branch.condition} ) {
if ( !${name} ) {
${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${anchor}.parentNode, ${anchor} );
}
} else if ( ${name} ) {
${name}.destroy( true );
${name} = null;
}
` );
}
}

function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {
const getBlock = block.getUniqueName( `get_block` );
const current_block = block.getUniqueName( `current_block` );

block.builders.create.addBlock( deindent`
function ${getBlock} ( ${params} ) {
Expand Down Expand Up @@ -93,8 +150,4 @@ export default function visitIfBlock ( generator, block, state, node ) {
}
` );
}

block.builders.destroy.addLine(
`if ( ${name} ) ${name}.destroy( ${isToplevel ? 'detach' : 'false'} );`
);
}
2 changes: 0 additions & 2 deletions src/generators/dom/visitors/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Comment from './Comment.js';
import EachBlock from './EachBlock.js';
import Element from './Element/Element.js';
import IfBlock from './IfBlock.js';
Expand All @@ -8,7 +7,6 @@ import Text from './Text.js';
import YieldTag from './YieldTag.js';

export default {
Comment,
EachBlock,
Element,
IfBlock,
Expand Down
4 changes: 2 additions & 2 deletions src/parse/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { locate } from 'locate-character';
import fragment from './state/fragment.js';
import { whitespace } from './patterns.js';
import { trimStart, trimEnd } from './utils/trim.js';
import { whitespace } from '../utils/patterns.js';
import { trimStart, trimEnd } from '../utils/trim.js';
import getCodeFrame from '../utils/getCodeFrame.js';
import hash from './utils/hash.js';

Expand Down
4 changes: 2 additions & 2 deletions src/parse/state/mustache.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import readExpression from '../read/expression.js';
import { whitespace } from '../patterns.js';
import { trimStart, trimEnd } from '../utils/trim.js';
import { whitespace } from '../../utils/patterns.js';
import { trimStart, trimEnd } from '../../utils/trim.js';

const validIdentifier = /[a-zA-Z_$][a-zA-Z0-9_$]*/;

Expand Down
2 changes: 1 addition & 1 deletion src/parse/state/tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import readExpression from '../read/expression.js';
import readScript from '../read/script.js';
import readStyle from '../read/style.js';
import { readEventHandlerDirective, readBindingDirective } from '../read/directives.js';
import { trimStart, trimEnd } from '../utils/trim.js';
import { trimStart, trimEnd } from '../../utils/trim.js';
import { decodeCharacterReferences } from '../utils/html.js';
import isVoidElementName from '../../utils/isVoidElementName.js';

Expand Down
2 changes: 1 addition & 1 deletion src/utils/CodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class CodeBuilder {
this.result += `\n\t${line}`;
} else {
if ( this.lastCondition ) {
this.result += `\n}`;
this.result += `\n}\n\n`;
}

this.result += `if ( ${condition} ) {\n\t${line}`;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/parse/utils/trim.js → src/utils/trim.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { whitespace } from '../patterns.js';
import { whitespace } from './patterns.js';

export function trimStart ( str ) {
let i = 0;
Expand Down
Loading