make visitors responsible for visiting their own children

pull/453/head
Rich-Harris 9 years ago
parent 00f1eaee12
commit 2d4f9eac00

@ -12,11 +12,10 @@ import processCss from './shared/processCss.js';
import annotateWithScopes from './annotateWithScopes.js'; import annotateWithScopes from './annotateWithScopes.js';
export default class Generator { export default class Generator {
constructor ( parsed, source, name, visitors, options ) { constructor ( parsed, source, name, options ) {
this.parsed = parsed; this.parsed = parsed;
this.source = source; this.source = source;
this.name = name; this.name = name;
this.visitors = visitors;
this.options = options; this.options = options;
this.imports = []; this.imports = [];
@ -434,27 +433,4 @@ export default class Generator {
this.current = newFragment; this.current = newFragment;
} }
visit ( node ) {
const visitor = this.visitors[ node.type ];
if ( !visitor ) throw new Error( `Not implemented: ${node.type}` );
if ( visitor.enter ) visitor.enter( this, node );
if ( visitor.type === 'Element' ) {
this.elementDepth += 1;
}
if ( node.children ) {
node.children.forEach( child => {
this.visit( child );
});
}
if ( visitor.type === 'Element' ) {
this.elementDepth -= 1;
}
if ( visitor.leave ) visitor.leave( this, node );
}
} }

@ -1,13 +1,13 @@
import deindent from '../../utils/deindent.js'; import deindent from '../../utils/deindent.js';
import getBuilders from './utils/getBuilders.js'; import getBuilders from './utils/getBuilders.js';
import CodeBuilder from '../../utils/CodeBuilder.js'; import CodeBuilder from '../../utils/CodeBuilder.js';
import visitors from './visitors/index.js'; import visit from './visit.js';
import Generator from '../Generator.js'; import Generator from '../Generator.js';
import * as shared from '../../shared/index.js'; import * as shared from '../../shared/index.js';
class DomGenerator extends Generator { class DomGenerator extends Generator {
constructor ( parsed, source, name, visitors, options ) { constructor ( parsed, source, name, options ) {
super( parsed, source, name, visitors, options ); super( parsed, source, name, options );
this.renderers = []; this.renderers = [];
this.uses = new Set(); this.uses = new Set();
@ -126,7 +126,7 @@ class DomGenerator extends Generator {
}); });
// walk the children here // walk the children here
node.children.forEach( node => this.visit( node ) ); node.children.forEach( node => visit( node, this ) );
this.addRenderer( this.current ); this.addRenderer( this.current );
this.pop(); this.pop();
@ -149,7 +149,7 @@ export default function dom ( parsed, source, options ) {
const format = options.format || 'es'; const format = options.format || 'es';
const name = options.name || 'SvelteComponent'; const name = options.name || 'SvelteComponent';
const generator = new DomGenerator( parsed, source, name, visitors, options ); const generator = new DomGenerator( parsed, source, name, options );
const { computations, hasJs, templateProperties, namespace } = generator.parseJs(); const { computations, hasJs, templateProperties, namespace } = generator.parseJs();
@ -177,7 +177,9 @@ export default function dom ( parsed, source, options ) {
getUniqueName, getUniqueName,
}); });
parsed.html.children.forEach( node => generator.visit( node ) ); parsed.html.children.forEach( node => {
visit( node, generator );
});
generator.addRenderer( generator.pop() ); generator.addRenderer( generator.pop() );

@ -0,0 +1,8 @@
import visitors from './visitors/index.js';
export default function visit ( node, generator ) {
const visitor = visitors[ node.type ];
if ( visitor.enter ) visitor.enter( generator, node );
if ( visitor.leave ) visitor.leave( generator, node );
}

@ -1,5 +1,6 @@
import deindent from '../../../utils/deindent.js'; import deindent from '../../../utils/deindent.js';
import CodeBuilder from '../../../utils/CodeBuilder.js'; import CodeBuilder from '../../../utils/CodeBuilder.js';
import visit from '../visit.js';
import addComponentAttributes from './attributes/addComponentAttributes.js'; import addComponentAttributes from './attributes/addComponentAttributes.js';
function capDown ( name ) { function capDown ( name ) {
@ -166,9 +167,15 @@ export default {
localElementDepth: current.localElementDepth + 1, localElementDepth: current.localElementDepth + 1,
key: null key: null
}); });
},
leave ( generator ) { this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
generator.pop(); generator.pop();
} }
}; };

@ -1,6 +1,7 @@
import CodeBuilder from '../../../utils/CodeBuilder.js'; import CodeBuilder from '../../../utils/CodeBuilder.js';
import deindent from '../../../utils/deindent.js'; import deindent from '../../../utils/deindent.js';
import getBuilders from '../utils/getBuilders.js'; import getBuilders from '../utils/getBuilders.js';
import visit from '../visit.js';
export default { export default {
enter ( generator, node ) { enter ( generator, node ) {
@ -214,9 +215,11 @@ export default {
builders: getBuilders(), builders: getBuilders(),
getUniqueName, getUniqueName,
}); });
},
leave ( generator ) { node.children.forEach( child => {
visit( child, generator );
});
generator.addRenderer( generator.current ); generator.addRenderer( generator.current );
generator.pop(); generator.pop();
} }

@ -1,5 +1,6 @@
import CodeBuilder from '../../../utils/CodeBuilder.js'; import CodeBuilder from '../../../utils/CodeBuilder.js';
import deindent from '../../../utils/deindent.js'; import deindent from '../../../utils/deindent.js';
import visit from '../visit.js';
import addElementAttributes from './attributes/addElementAttributes.js'; import addElementAttributes from './attributes/addElementAttributes.js';
import Component from './Component.js'; import Component from './Component.js';
import Window from './meta/Window.js'; import Window from './meta/Window.js';
@ -108,20 +109,20 @@ export default {
localElementDepth: generator.current.localElementDepth + 1, localElementDepth: generator.current.localElementDepth + 1,
key: null key: null
}); });
},
leave ( generator, node ) { this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
if ( node.name in meta ) { if ( node.name in meta ) {
if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node ); if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node );
return; return;
} }
const isComponent = generator.components.has( node.name );
if ( isComponent ) {
return Component.leave( generator, node );
}
if ( node.initialUpdate ) { if ( node.initialUpdate ) {
generator.current.builders.init.addBlock( node.initialUpdate ); generator.current.builders.init.addBlock( node.initialUpdate );
} }

@ -1,12 +1,12 @@
import deindent from '../../utils/deindent.js'; import deindent from '../../utils/deindent.js';
import CodeBuilder from '../../utils/CodeBuilder.js'; import CodeBuilder from '../../utils/CodeBuilder.js';
import flattenReference from '../../utils/flattenReference.js'; import flattenReference from '../../utils/flattenReference.js';
import visitors from './visitors/index.js';
import Generator from '../Generator.js'; import Generator from '../Generator.js';
import visit from './visit.js';
class SsrGenerator extends Generator { class SsrGenerator extends Generator {
constructor ( parsed, source, name, visitors, options ) { constructor ( parsed, source, name, options ) {
super( parsed, source, name, visitors, options ); super( parsed, source, name, options );
this.bindings = []; this.bindings = [];
this.renderCode = ''; this.renderCode = '';
} }
@ -38,7 +38,7 @@ export default function ssr ( parsed, source, options ) {
const format = options.format || 'cjs'; const format = options.format || 'cjs';
const name = options.name || 'SvelteComponent'; const name = options.name || 'SvelteComponent';
const generator = new SsrGenerator( parsed, source, name, visitors, options ); const generator = new SsrGenerator( parsed, source, name, options );
const { computations, hasJs, templateProperties } = generator.parseJs( true ); const { computations, hasJs, templateProperties } = generator.parseJs( true );
@ -56,7 +56,9 @@ export default function ssr ( parsed, source, options ) {
conditions: [] conditions: []
}); });
parsed.html.children.forEach( node => generator.visit( node ) ); parsed.html.children.forEach( node => {
visit( node, generator );
});
builders.render.addLine( builders.render.addLine(
templateProperties.data ? `root = Object.assign( ${generator.alias( 'template' )}.data(), root || {} );` : `root = root || {};` templateProperties.data ? `root = Object.assign( ${generator.alias( 'template' )}.data(), root || {} );` : `root = root || {};`

@ -0,0 +1,8 @@
import visitors from './visitors/index.js';
export default function visit ( node, generator ) {
const visitor = visitors[ node.type ];
if ( visitor.enter ) visitor.enter( generator, node );
if ( visitor.leave ) visitor.leave( generator, node );
}

@ -1,4 +1,5 @@
import flattenReference from '../../../utils/flattenReference.js'; import flattenReference from '../../../utils/flattenReference.js';
import visit from '../visit.js';
export default { export default {
enter ( generator, node ) { enter ( generator, node ) {
@ -63,9 +64,15 @@ export default {
} }
generator.append( open ); generator.append( open );
},
leave ( generator, node ) { this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
const close = node.children.length ? `\` })}` : ')}'; const close = node.children.length ? `\` })}` : ')}';
generator.append( close ); generator.append( close );
} }

@ -1,3 +1,5 @@
import visit from '../visit.js';
export default { export default {
enter ( generator, node ) { enter ( generator, node ) {
const { dependencies, snippet } = generator.contextualise( node.expression ); const { dependencies, snippet } = generator.contextualise( node.expression );
@ -21,9 +23,11 @@ export default {
indexes, indexes,
contextDependencies contextDependencies
}); });
},
leave ( generator ) { node.children.forEach( child => {
visit( child, generator );
});
const close = `\` ).join( '' )}`; const close = `\` ).join( '' )}`;
generator.append( close ); generator.append( close );

@ -1,5 +1,6 @@
import Component from './Component.js'; import Component from './Component.js';
import isVoidElementName from '../../../utils/isVoidElementName.js'; import isVoidElementName from '../../../utils/isVoidElementName.js';
import visit from '../visit.js';
import Window from './meta/Window.js'; import Window from './meta/Window.js';
const meta = { const meta = {
@ -45,9 +46,15 @@ export default {
openingTag += '>'; openingTag += '>';
generator.append( openingTag ); generator.append( openingTag );
},
leave ( generator, node ) { this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
if ( node.name in meta ) { if ( node.name in meta ) {
if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node ); if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node );
return; return;

@ -1,3 +1,5 @@
import visit from '../visit.js';
export default { export default {
enter ( generator, node ) { enter ( generator, node ) {
const { snippet } = generator.contextualise( node.expression ); const { snippet } = generator.contextualise( node.expression );
@ -7,11 +9,19 @@ export default {
generator.push({ generator.push({
conditions: generator.current.conditions.concat( snippet ) conditions: generator.current.conditions.concat( snippet )
}); });
},
leave ( generator, node ) { node.children.forEach( child => {
visit( child, generator );
});
generator.append( '` : `' ); generator.append( '` : `' );
if ( node.else ) node.else.children.forEach( child => generator.visit( child ) );
if ( node.else ) {
node.else.children.forEach( child => {
visit( child, generator );
});
}
generator.append( '` }' ); generator.append( '` }' );
generator.pop(); generator.pop();

Loading…
Cancel
Save