0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00

fix destructuring in slot let binding

This commit is contained in:
Tan Li Hau 2019-12-24 00:15:23 +08:00 committed by Conduitry
parent 5486d67adf
commit 75b8d3fb21
4 changed files with 140 additions and 5 deletions

View File

@ -7,7 +7,7 @@ import { BinaryExpression } from 'estree';
export function get_slot_definition(block: Block, scope: TemplateScope, lets: Let[]) {
if (lets.length === 0) return { block, scope };
const input = {
const context_input = {
type: 'ObjectPattern',
properties: lets.map(l => ({
type: 'Property',
@ -17,10 +17,41 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
}))
};
const properties = [];
const value_map = new Map();
lets.forEach(l => {
let value;
if (l.names.length > 1) {
// more than one, probably destructuring
const unique_name = block.get_unique_name(l.names.join('_')).name;
value_map.set(l.value, unique_name);
value = { type: 'Identifier', name: unique_name };
} else {
value = l.value || l.name;
}
properties.push({
type: 'Property',
kind: 'init',
key: l.name,
value,
});
});
const changes_input = {
type: 'ObjectPattern',
properties,
};
const names: Set<string> = new Set();
const names_lookup: Map<string, string> = new Map();
lets.forEach(l => {
l.names.forEach(name => {
names.add(name);
if (value_map.has(l.value)) {
names_lookup.set(name, value_map.get(l.value));
}
});
});
@ -43,8 +74,10 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
const i = context_lookup.get(name).index.value as number;
const g = Math.floor(i / 31);
const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
if (!grouped[g]) grouped[g] = [];
grouped[g].push({ name, n: i % 31 });
grouped[g].push({ name: lookup_name, n: i % 31 });
});
const elements = [];
@ -65,8 +98,9 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
return Array.from(names)
.map(name => {
const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name;
const i = context_lookup.get(name).index.value as number;
return x`${name} ? ${1 << i} : 0`;
return x`${lookup_name} ? ${1 << i} : 0`;
})
.reduce((lhs, rhs) => x`${lhs} | ${rhs}`) as BinaryExpression;
}
@ -75,7 +109,7 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le
return {
block,
scope,
get_context: x`${input} => ${context}`,
get_changes: x`${input} => ${changes}`
get_context: x`${context_input} => ${context}`,
get_changes: x`${changes_input} => ${changes}`
};
}

View File

@ -0,0 +1,5 @@
<script>
export let props;
</script>
<slot value={props} data={Array.isArray(props) ? props[0] : props.a} />

View File

@ -0,0 +1,68 @@
export default {
html: `
<div>
hello world 0 hello
<button>Increment</button>
</div>
<div>
hello world 0 hello
<button>Increment</button>
</div>
<div>
hello world 0 hello
<button>Increment</button>
</div>
`,
async test({ assert, component, target, window }) {
const [button1, button2, button3] = target.querySelectorAll('button');
const event = new window.MouseEvent('click');
await button1.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<div>
hello world 1 hello
<button>Increment</button>
</div>
<div>
hello world 0 hello
<button>Increment</button>
</div>
<div>
hello world 0 hello
<button>Increment</button>
</div>
`);
await button2.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<div>
hello world 1 hello
<button>Increment</button>
</div>
<div>
hello world 1 hello
<button>Increment</button>
</div>
<div>
hello world 0 hello
<button>Increment</button>
</div>
`);
await button3.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<div>
hello world 1 hello
<button>Increment</button>
</div>
<div>
hello world 1 hello
<button>Increment</button>
</div>
<div>
hello world 1 hello
<button>Increment</button>
</div>
`);
}
};

View File

@ -0,0 +1,28 @@
<script>
import Nested from "./Nested.svelte";
let c = 0, d = 0, e = 0;
</script>
<div>
<Nested props={['hello', 'world']} let:value={pair} let:data={foo}>
{pair[0]} {pair[1]} {c} {foo}
</Nested>
<button on:click={() => { c += 1; }}>Increment</button>
</div>
<div>
<Nested props={['hello', 'world']} let:value={[a, b]} let:data={foo}>
{a} {b} {d} {foo}
</Nested>
<button on:click={() => { d += 1; }}>Increment</button>
</div>
<div>
<Nested props={{ a: 'hello', b: 'world' }} let:value={{ a, b }} let:data={foo}>
{a} {b} {e} {foo}
</Nested>
<button on:click={() => { e += 1; }}>Increment</button>
</div>