Skip to content

Commit

Permalink
merge master -> gh-185
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Dec 15, 2016
2 parents 1cfbfb0 + 14ef2ed commit 6444e8d
Show file tree
Hide file tree
Showing 37 changed files with 744 additions and 431 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Svelte changelog

## 1.2.4

* SSR compiler: Implement `{{{tripes}}}` ([#197](https://github.com/sveltejs/svelte/issues/197))
* SSR compiler: Escape HTML in tags ([#197](https://github.com/sveltejs/svelte/issues/197))

## 1.2.3

* Add support for `namespace` declaration for SVG (etc) components ([#147](https://github.com/sveltejs/svelte/issues/147))
* Throw error if methods or lifecycle hooks are arrow functions that use `this` or `arguments` ([#179](https://github.com/sveltejs/svelte/issues/179))
* Use `setAttribute()` for `list` attributes, to preserve link to `<datalist>` ([#178](https://github.com/sveltejs/svelte/issues/178))
* Throw error if default export is not an object literal ([#190](https://github.com/sveltejs/svelte/pull/190))
* Internal refactoring

## 1.2.2

* Omit directives in server-side rendering ([#163](https://github.com/sveltejs/svelte/issues/167))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "1.2.2",
"version": "1.2.4",
"description": "The magical disappearing UI framework",
"main": "compiler/svelte.js",
"files": [
Expand Down
225 changes: 225 additions & 0 deletions src/generate/createGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import MagicString from 'magic-string';
import CodeBuilder from '../utils/CodeBuilder.js';
import { walk } from 'estree-walker';
import deindent from '../utils/deindent.js';
import isReference from '../utils/isReference.js';
import counter from './utils/counter.js';
import flattenReference from '../utils/flattenReference.js';
import visitors from './visitors/index.js';
import globalWhitelist from '../utils/globalWhitelist.js';

export default function createGenerator ( parsed, source, names ) {
const generator = {
addElement ( name, renderStatement, needsIdentifier = false ) {
const isToplevel = generator.current.localElementDepth === 0;
if ( needsIdentifier || isToplevel ) {
generator.current.builders.init.addLine(
`var ${name} = ${renderStatement};`
);

generator.createMountStatement( name );
} else {
generator.current.builders.init.addLine(
`${generator.current.target}.appendChild( ${renderStatement} );`
);
}

if ( isToplevel ) {
generator.current.builders.detach.addLine(
`${name}.parentNode.removeChild( ${name} );`
);
}
},

createMountStatement ( name ) {
if ( generator.current.target === 'target' ) {
generator.current.builders.mount.addLine(
`target.insertBefore( ${name}, anchor );`
);
} else {
generator.current.builders.init.addLine(
`${generator.current.target}.appendChild( ${name} );` );
}
},

createAnchor ( _name, description = '' ) {
const name = `${_name}_anchor`;
const statement = `document.createComment( ${JSON.stringify( description )} )`;
generator.addElement( name, statement, true );
return name;
},

generateBlock ( node, name ) {
generator.push({
name,
target: 'target',
localElementDepth: 0,
builders: generator.getBuilders(),
getUniqueName: generator.getUniqueNameMaker()
});
// walk the children here
node.children.forEach( generator.visit );
generator.addRenderer( generator.current );
generator.pop();
// unset the children, to avoid them being visited again
node.children = [];
},

renderers: [],

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}
}
` );
}

generator.renderers.push( deindent`
function ${fragment.name} ( ${fragment.params}, component ) {
${fragment.builders.init}
return {
mount: function ( target, anchor ) {
${fragment.builders.mount}
},
update: function ( changed, ${fragment.params} ) {
${fragment.builders.update}
},
teardown: function ( detach ) {
${fragment.builders.teardown}
}
};
}
` );
},

addSourcemapLocations ( node ) {
walk( node, {
enter ( node ) {
generator.code.addSourcemapLocation( node.start );
generator.code.addSourcemapLocation( node.end );
}
});
},

code: new MagicString( source ),

components: {},

contextualise ( expression, isEventHandler ) {
const usedContexts = [];
const dependencies = [];

const { contextDependencies, contexts, indexes } = generator.current;

walk( expression, {
enter ( node, parent ) {
if ( isReference( node, parent ) ) {
const { name } = flattenReference( node );

if ( parent && parent.type === 'CallExpression' && node === parent.callee && generator.helpers[ name ] ) {
generator.code.prependRight( node.start, `template.helpers.` );
return;
}

if ( name === 'event' && isEventHandler ) {
return;
}

if ( contexts[ name ] ) {
dependencies.push( ...contextDependencies[ name ] );
if ( !~usedContexts.indexOf( name ) ) usedContexts.push( name );
} else if ( indexes[ name ] ) {
const context = indexes[ name ];
if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
} else if ( !globalWhitelist[ name ] ) {
dependencies.push( name );
generator.code.prependRight( node.start, `root.` );
if ( !~usedContexts.indexOf( 'root' ) ) usedContexts.push( 'root' );
}

this.skip();
}
}
});

return {
dependencies,
contexts: usedContexts,
snippet: `[✂${expression.start}-${expression.end}✂]`,
string: generator.code.slice( expression.start, expression.end )
};
},

events: {},

getBuilders () {
return {
init: new CodeBuilder(),
mount: new CodeBuilder(),
update: new CodeBuilder(),
detach: new CodeBuilder(),
detachRaw: new CodeBuilder(),
teardown: new CodeBuilder()
};
},

getUniqueName: counter( names ),

getUniqueNameMaker () {
return counter( names );
},

cssId: parsed.css ? `svelte-${parsed.hash}` : '',

helpers: {},

pop () {
const tail = generator.current;
generator.current = tail.parent;

return tail;
},

push ( fragment ) {
const newFragment = Object.assign( {}, generator.current, fragment, {
parent: generator.current
});

generator.current = newFragment;
},

usesRefs: false,

source,

visit ( node ) {
const visitor = visitors[ node.type ];
if ( !visitor ) throw new Error( `Not implemented: ${node.type}` );

if ( visitor.enter ) visitor.enter( generator, node );

if ( node.children ) {
node.children.forEach( child => {
generator.visit( child );
});
}

if ( visitor.leave ) visitor.leave( generator, node );
}
};

return generator;
}
Loading

0 comments on commit 6444e8d

Please sign in to comment.