various fixes

pull/3539/head
Richard Harris 6 years ago
parent 23167da0dd
commit 1e2f29bf4e

@ -78,7 +78,7 @@ export default class Renderer {
}); });
this.literal.expressions.push(node); this.literal.expressions.push(node);
this.current = { value: '' }; this.current.value = '';
} }
push() { push() {

@ -66,22 +66,20 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
const slot = node.get_static_attribute_value('slot'); const slot = node.get_static_attribute_value('slot');
const nearest_inline_component = node.find_nearest(/InlineComponent/); const nearest_inline_component = node.find_nearest(/InlineComponent/);
if (slot && nearest_inline_component) {
const slot = node.attributes.find((attribute) => attribute.name === 'slot');
const slot_name = (slot.chunks[0] as Text).data;
const target = renderer.targets[renderer.targets.length - 1];
target.slot_stack.push(slot_name);
target.slots[slot_name] = '';
const lets = node.lets; // if (slot && nearest_inline_component) {
const seen = new Set(lets.map(l => l.name.name)); // const slot = node.attributes.find((attribute) => attribute.name === 'slot');
// const slot_name = (slot.chunks[0] as Text).data;
nearest_inline_component.lets.forEach(l => { // const lets = node.lets;
if (!seen.has(l.name.name)) lets.push(l); // const seen = new Set(lets.map(l => l.name.name));
});
options.slot_scopes.set(slot_name, get_slot_scope(node.lets)); // nearest_inline_component.lets.forEach(l => {
} // if (!seen.has(l.name.name)) lets.push(l);
// });
// options.slot_scopes.set(slot_name, get_slot_scope(node.lets));
// }
const class_expression = node.classes.map((class_directive: Class) => { const class_expression = node.classes.map((class_directive: Class) => {
const { expression, name } = class_directive; const { expression, name } = class_directive;
@ -189,6 +187,21 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
} else { } else {
renderer.add_expression(node_contents); renderer.add_expression(node_contents);
} }
} else if (slot && nearest_inline_component) {
renderer.push();
renderer.render(node.children, options);
const lets = node.lets;
const seen = new Set(lets.map(l => l.name.name));
nearest_inline_component.lets.forEach(l => {
if (!seen.has(l.name.name)) lets.push(l);
});
options.slot_scopes.set(slot, {
input: get_slot_scope(node.lets),
output: renderer.pop()
});
} else { } else {
renderer.render(node.children, options); renderer.render(node.children, options);
} }

@ -36,17 +36,16 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend
let props; let props;
if (uses_spread) { if (uses_spread) {
props = `@_Object.assign(${ props = x`@_Object.assign(${
node.attributes node.attributes
.map(attribute => { .map(attribute => {
if (attribute.is_spread) { if (attribute.is_spread) {
return snip(attribute.expression); return attribute.expression.node;
} else { } else {
return `{ ${quote_name_if_necessary(attribute.name)}: ${get_prop_value(attribute)} }`; return x`{ ${attribute.name}: ${get_prop_value(attribute)} }`;
} }
}) })
.concat(binding_props.map(p => `{ ${p} }`)) .concat(binding_props.map(p => `{ ${p} }`))
.join(', ')
})`; })`;
} else { } else {
props = x`{ props = x`{
@ -61,7 +60,7 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend
const expression = ( const expression = (
node.name === 'svelte:self' node.name === 'svelte:self'
? '__svelte:self__' // TODO conflict-proof this ? options.name
: node.name === 'svelte:component' : node.name === 'svelte:component'
? x`(${node.expression.node}) || @missing_component` ? x`(${node.expression.node}) || @missing_component`
: node.name : node.name

@ -5,6 +5,7 @@ import { stringify, string_literal } from '../utils/stringify';
import Renderer from './Renderer'; import Renderer from './Renderer';
import { INode as TemplateNode } from '../nodes/interfaces'; // TODO import { INode as TemplateNode } from '../nodes/interfaces'; // TODO
import Text from '../nodes/Text'; import Text from '../nodes/Text';
import { extract_names } from '../utils/scope';
export default function ssr( export default function ssr(
component: Component, component: Component,
@ -32,14 +33,15 @@ export default function ssr(
.map(({ name }) => { .map(({ name }) => {
const store_name = name.slice(1); const store_name = name.slice(1);
const store = component.var_lookup.get(store_name); const store = component.var_lookup.get(store_name);
if (store && store.hoistable) return; if (store && store.hoistable) return null;
const assignment = `${name} = @get_store_value(${store_name});`; const assignment = b`${name} = @get_store_value(${store_name});`;
return component.compile_options.dev return component.compile_options.dev
? `@validate_store(${store_name}, '${store_name}'); ${assignment}` ? b`@validate_store(${store_name}, '${store_name}'); ${assignment}`
: assignment; : assignment;
}); })
.filter(Boolean);
// TODO remove this, just use component.vars everywhere // TODO remove this, just use component.vars everywhere
const props = component.vars.filter(variable => !variable.module && variable.export_name); const props = component.vars.filter(variable => !variable.module && variable.export_name);
@ -67,33 +69,35 @@ export default function ssr(
}) })
: []; : [];
const reactive_declarations = component.reactive_declarations.map(_d => { const reactive_declarations = component.reactive_declarations.map(d => {
throw new Error('TODO'); let snippet = b`${d.node}`;
// let snippet = `[✂${d.node.body.start}-${d.node.end}✂]`;
if (d.declaration) {
// if (d.declaration) { const declared = extract_names(d.declaration);
// const declared = extract_names(d.declaration); const injected = declared.filter(name => {
// const injected = declared.filter(name => { return name[0] !== '$' && component.var_lookup.get(name).injected;
// return name[0] !== '$' && component.var_lookup.get(name).injected; });
// });
const self_dependencies = injected.filter(name => d.dependencies.has(name));
// const self_dependencies = injected.filter(name => d.dependencies.has(name));
if (injected.length) {
// if (injected.length) { // in some cases we need to do `let foo; [expression]`, in
// // in some cases we need to do `let foo; [expression]`, in // others we can do `let [expression]`
// // others we can do `let [expression]` const separate = (
// const separate = ( self_dependencies.length > 0 ||
// self_dependencies.length > 0 || declared.length > injected.length
// declared.length > injected.length );
// );
snippet = separate
// snippet = separate ? b`
// ? `let ${injected.join(', ')}; ${snippet}` ${injected.map(name => b`let ${name};`)}
// : `let ${snippet}`; ${snippet}`
// } : b`
// } let ${snippet}`;
}
// return snippet; }
return snippet;
}); });
const main = renderer.has_bindings const main = renderer.has_bindings

@ -1,4 +0,0 @@
export function snip(expression) {
throw new Error(`snip bad`);
return `[✂${expression.node.start}-${expression.node.end}✂]`;
}

@ -1,20 +1,52 @@
export default { export default {
html: `<div>foo</div><div>bar</div><div>baz</div>`, props: {
state: 'deconflicted',
states: [
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'...and some others'
]
},
html: `
<p>Current state: deconflicted</p>
<ul>
<li>Alabama</li>
<li>Alaska</li>
<li>Arizona</li>
<li>Arkansas</li>
<li>...and some others</li>
</ul>
`,
test({ assert, component, target }) { test({ assert, component, target }) {
let elems = target.querySelectorAll('div'); component.states = [
assert.equal(component.divs.length, 3, 'three divs are registered (unkeyed array)'); 'Maine',
component.divs.forEach((e, i) => { 'Maryland',
assert.equal(e, elems[i], `div ${i} is correct (unkeyed array)`); 'Massachusetts',
}); 'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana'
];
component.items = ['foo', 'baz']; assert.htmlEqual( target.innerHTML, `
assert.equal(component.divs.length, 3, 'the divs array is still 3 long'); <p>Current state: deconflicted</p>
assert.equal(component.divs[2], null, 'the last div is unregistered');
elems = target.querySelectorAll('div'); <ul>
component.divs.forEach((e, i) => { <li>Maine</li>
assert.equal(e, elems[i], `div ${i} is still correct`); <li>Maryland</li>
}); <li>Massachusetts</li>
<li>Michigan</li>
<li>Minnesota</li>
<li>Mississippi</li>
<li>Missouri</li>
<li>Montana</li>
</ul>
` );
} }
}; };

@ -1,8 +1,12 @@
<script> <script>
export let items = ['foo', 'bar', 'baz']; export let state;
export let divs = []; export let states;
</script> </script>
{#each items as item, j} <p>Current state: {state}</p>
<div bind:this={divs[j]}>{item}</div>
<ul>
{#each states as state}
<li>{state}</li>
{/each} {/each}
</ul>
Loading…
Cancel
Save