Merge pull request #332 from sveltejs/gh-51

self-references
pull/339/head
Rich Harris 8 years ago committed by GitHub
commit 319b3b6765

@ -9,9 +9,10 @@ import getOutro from './shared/utils/getOutro.js';
import annotateWithScopes from './annotateWithScopes.js';
export default class Generator {
constructor ( parsed, source, names, visitors ) {
constructor ( parsed, source, name, names, visitors ) {
this.parsed = parsed;
this.source = source;
this.name = name;
this.names = names;
this.visitors = visitors;

@ -8,8 +8,8 @@ import Generator from '../Generator.js';
import * as shared from '../../shared/index.js';
class DomGenerator extends Generator {
constructor ( parsed, source, names, visitors ) {
super( parsed, source, names, visitors );
constructor ( parsed, source, name, names, visitors ) {
super( parsed, source, name, names, visitors );
this.renderers = [];
this.uses = {};
@ -152,7 +152,7 @@ export default function dom ( parsed, source, options, names ) {
const format = options.format || 'es';
const name = options.name || 'SvelteComponent';
const generator = new DomGenerator( parsed, source, names, visitors );
const generator = new DomGenerator( parsed, source, name, names, visitors );
const { computations, templateProperties } = generator.parseJs();

@ -2,10 +2,14 @@ import deindent from '../../../utils/deindent.js';
import CodeBuilder from '../../../utils/CodeBuilder.js';
import addComponentAttributes from './attributes/addComponentAttributes.js';
function capDown ( name ) {
return `${name[0].toLowerCase()}${name.slice( 1 )}`;
}
export default {
enter ( generator, node ) {
const hasChildren = node.children.length > 0;
const name = generator.current.getUniqueName( `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` );
const name = generator.current.getUniqueName( capDown( node.name === ':Self' ? generator.name : node.name ) );
const local = {
name,
@ -104,9 +108,11 @@ export default {
componentInitProperties.push(`data: ${name}_initialData`);
}
const expression = node.name === ':Self' ? generator.name : `template.components.${node.name}`;
local.init.addBlockAtStart( deindent`
${statements.join( '\n\n' )}
var ${name} = new template.components.${node.name}({
var ${name} = new ${expression}({
${componentInitProperties.join(',\n')}
});
` );

@ -5,7 +5,7 @@ import Component from './Component.js';
export default {
enter ( generator, node ) {
const isComponent = node.name in generator.components;
const isComponent = node.name in generator.components || node.name === ':Self';
if ( isComponent ) {
return Component.enter( generator, node );
}

@ -5,8 +5,8 @@ import visitors from './visitors/index.js';
import Generator from '../Generator.js';
class SsrGenerator extends Generator {
constructor ( parsed, source, names, visitors ) {
super( parsed, source, names, visitors );
constructor ( parsed, source, name, names, visitors ) {
super( parsed, source, name, names, visitors );
this.bindings = [];
this.renderCode = '';
}
@ -18,7 +18,7 @@ class SsrGenerator extends Generator {
this.bindings.push( deindent`
if ( ${conditions.join( '&&' )} ) {
tmp = template.components.${name}.data();
tmp = ${name}.data();
if ( '${binding.value}' in tmp ) {
root.${binding.name} = tmp.${binding.value};
settled = false;
@ -36,7 +36,7 @@ export default function ssr ( parsed, source, options, names ) {
const format = options.format || 'cjs';
const name = options.name || 'SvelteComponent';
const generator = new SsrGenerator( parsed, source, names, visitors );
const generator = new SsrGenerator( parsed, source, name, names, visitors );
const { computations, templateProperties } = generator.parseJs();

@ -43,11 +43,13 @@ export default {
})
.join( ', ' );
const expression = node.name === ':Self' ? generator.name : `template.components.${node.name}`;
bindings.forEach( binding => {
generator.addBinding( binding, node.name );
generator.addBinding( binding, expression );
});
let open = `\${template.components.${node.name}.render({${props}}`;
let open = `\${${expression}.render({${props}}`;
if ( node.children.length ) {
open += `, { yield: () => \``;

@ -3,7 +3,7 @@ import voidElementNames from '../../../utils/voidElementNames.js';
export default {
enter ( generator, node ) {
if ( node.name in generator.components ) {
if ( node.name in generator.components || node.name === ':Self' ) {
Component.enter( generator, node );
return;
}
@ -39,7 +39,7 @@ export default {
},
leave ( generator, node ) {
if ( node.name in generator.components ) {
if ( node.name in generator.components || node.name === ':Self' ) {
Component.leave( generator, node );
return;
}

@ -9,6 +9,8 @@ import voidElementNames from '../../utils/voidElementNames.js';
const validTagName = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
const invalidUnquotedAttributeCharacters = /[\s"'=<>\/`]/;
const SELF = ':Self';
const specials = {
script: {
read: readScript,
@ -170,6 +172,27 @@ export default function tag ( parser ) {
function readTagName ( parser ) {
const start = parser.index;
if ( parser.eat( SELF ) ) {
// check we're inside a block, otherwise this
// will cause infinite recursion
let i = parser.stack.length;
let legal = false;
while ( i-- ) {
const fragment = parser.stack[i];
if ( fragment.type === 'IfBlock' || fragment.type === 'ElseBlock' ) {
legal = true;
break;
}
}
if ( !legal ) {
parser.error( `<${SELF}> components can only exist inside if-blocks or each-blocks`, start );
}
return SELF;
}
const name = parser.readUntil( /(\s|\/|>)/ );
if ( !validTagName.test( name ) ) {
parser.error( `Expected valid tag name`, start );

@ -0,0 +1,14 @@
export default {
data: {
depth: 5
},
html: `
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
<span>0</span>
`
};

@ -0,0 +1,4 @@
<span>{{depth}}</span>
{{#if depth > 0}}
<:Self depth='{{depth - 1}}'/>
{{/if}}

@ -0,0 +1,8 @@
{
"message": "<:Self> components can only exist inside if-blocks or each-blocks",
"loc": {
"line": 1,
"column": 1
},
"pos": 1
}

@ -0,0 +1,3 @@
{{#if depth > 1}}
<:Self depth='{{depth - 1}}'/>
{{/if}}

@ -0,0 +1,79 @@
{
"hash": 1792372370,
"html": {
"start": 0,
"end": 57,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 57,
"type": "IfBlock",
"expression": {
"type": "BinaryExpression",
"start": 6,
"end": 15,
"left": {
"type": "Identifier",
"start": 6,
"end": 11,
"name": "depth"
},
"operator": ">",
"right": {
"type": "Literal",
"start": 14,
"end": 15,
"value": 1,
"raw": "1"
}
},
"children": [
{
"start": 19,
"end": 49,
"type": "Element",
"name": ":Self",
"attributes": [
{
"start": 26,
"end": 47,
"type": "Attribute",
"name": "depth",
"value": [
{
"start": 33,
"end": 46,
"type": "MustacheTag",
"expression": {
"type": "BinaryExpression",
"start": 35,
"end": 44,
"left": {
"type": "Identifier",
"start": 35,
"end": 40,
"name": "depth"
},
"operator": "-",
"right": {
"type": "Literal",
"start": 43,
"end": 44,
"value": 1,
"raw": "1"
}
}
}
]
}
],
"children": []
}
]
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save