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';
export default class Generator {
constructor ( parsed, source, name, visitors, options ) {
constructor ( parsed, source, name, options ) {
this.parsed = parsed;
this.source = source;
this.name = name;
this.visitors = visitors;
this.options = options;
this.imports = [];
@ -434,27 +433,4 @@ export default class Generator {
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 getBuilders from './utils/getBuilders.js';
import CodeBuilder from '../../utils/CodeBuilder.js';
import visitors from './visitors/index.js';
import visit from './visit.js';
import Generator from '../Generator.js';
import * as shared from '../../shared/index.js';
class DomGenerator extends Generator {
constructor ( parsed, source, name, visitors, options ) {
super( parsed, source, name, visitors, options );
constructor ( parsed, source, name, options ) {
super( parsed, source, name, options );
this.renderers = [];
this.uses = new Set();
@ -126,7 +126,7 @@ class DomGenerator extends Generator {
});
// walk the children here
node.children.forEach( node => this.visit( node ) );
node.children.forEach( node => visit( node, this ) );
this.addRenderer( this.current );
this.pop();
@ -149,7 +149,7 @@ export default function dom ( parsed, source, options ) {
const format = options.format || 'es';
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();
@ -177,7 +177,9 @@ export default function dom ( parsed, source, options ) {
getUniqueName,
});
parsed.html.children.forEach( node => generator.visit( node ) );
parsed.html.children.forEach( node => {
visit( node, generator );
});
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 CodeBuilder from '../../../utils/CodeBuilder.js';
import visit from '../visit.js';
import addComponentAttributes from './attributes/addComponentAttributes.js';
function capDown ( name ) {
@ -166,9 +167,15 @@ export default {
localElementDepth: current.localElementDepth + 1,
key: null
});
},
leave ( generator ) {
this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
generator.pop();
}
};

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

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

@ -1,12 +1,12 @@
import deindent from '../../utils/deindent.js';
import CodeBuilder from '../../utils/CodeBuilder.js';
import flattenReference from '../../utils/flattenReference.js';
import visitors from './visitors/index.js';
import Generator from '../Generator.js';
import visit from './visit.js';
class SsrGenerator extends Generator {
constructor ( parsed, source, name, visitors, options ) {
super( parsed, source, name, visitors, options );
constructor ( parsed, source, name, options ) {
super( parsed, source, name, options );
this.bindings = [];
this.renderCode = '';
}
@ -38,7 +38,7 @@ export default function ssr ( parsed, source, options ) {
const format = options.format || 'cjs';
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 );
@ -56,7 +56,9 @@ export default function ssr ( parsed, source, options ) {
conditions: []
});
parsed.html.children.forEach( node => generator.visit( node ) );
parsed.html.children.forEach( node => {
visit( node, generator );
});
builders.render.addLine(
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 visit from '../visit.js';
export default {
enter ( generator, node ) {
@ -63,9 +64,15 @@ export default {
}
generator.append( open );
},
leave ( generator, node ) {
this.elementDepth += 1;
node.children.forEach( child => {
visit( child, generator );
});
this.elementDepth -= 1;
const close = node.children.length ? `\` })}` : ')}';
generator.append( close );
}

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

@ -1,5 +1,6 @@
import Component from './Component.js';
import isVoidElementName from '../../../utils/isVoidElementName.js';
import visit from '../visit.js';
import Window from './meta/Window.js';
const meta = {
@ -45,9 +46,15 @@ export default {
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 ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node );
return;

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

Loading…
Cancel
Save