mirror of https://github.com/sveltejs/svelte
fix: object destructuring picks up computed properties (#8386)
fixes #6609. Prior related PR: #8357pull/8387/head
parent
4b0b471ee1
commit
a1e8421368
@ -1,24 +1,33 @@
|
||||
import ConstTag from '../../../nodes/ConstTag';
|
||||
import Block from '../../Block';
|
||||
import { b, x } from 'code-red';
|
||||
import { b, Node, x } from 'code-red';
|
||||
import Renderer from '../../Renderer';
|
||||
import Expression from '../../../nodes/shared/Expression';
|
||||
|
||||
export function add_const_tags(block: Block, const_tags: ConstTag[], ctx: string) {
|
||||
const const_tags_props = [];
|
||||
const_tags.forEach((const_tag, i) => {
|
||||
const name = `#constants_${i}`;
|
||||
const_tags_props.push(b`const ${name} = ${const_tag.expression.manipulate(block, ctx)}`);
|
||||
const_tag.contexts.forEach(context => {
|
||||
const_tags_props.push(b`${ctx}[${block.renderer.context_lookup.get(context.key.name).index}] = ${context.default_modifier(context.modifier({ type: 'Identifier', name }), name => block.renderer.context_lookup.has(name) ? x`${ctx}[${block.renderer.context_lookup.get(name).index}]` : { type: 'Identifier', name })};`);
|
||||
});
|
||||
});
|
||||
return const_tags_props;
|
||||
const const_tags_props = [];
|
||||
const_tags.forEach((const_tag, i) => {
|
||||
const name = `#constants_${i}`;
|
||||
const_tags_props.push(b`const ${name} = ${const_tag.expression.manipulate(block, ctx)}`);
|
||||
const to_ctx = (name: string) => block.renderer.context_lookup.has(name) ? x`${ctx}[${block.renderer.context_lookup.get(name).index}]` : { type: 'Identifier', name } as Node;
|
||||
|
||||
const_tag.contexts.forEach(context => {
|
||||
if (context.type === 'DestructuredVariable') {
|
||||
const_tags_props.push(b`${ctx}[${block.renderer.context_lookup.get(context.key.name).index}] = ${context.default_modifier(context.modifier({ type: 'Identifier', name }), to_ctx)}`);
|
||||
} else {
|
||||
const expression = new Expression(block.renderer.component, const_tag, const_tag.scope, context.key);
|
||||
const_tags_props.push(b`const ${context.property_name} = ${expression.manipulate(block, ctx)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
return const_tags_props;
|
||||
}
|
||||
|
||||
export function add_const_tags_context(renderer: Renderer, const_tags: ConstTag[]) {
|
||||
const_tags.forEach(const_tag => {
|
||||
const_tag.contexts.forEach(context => {
|
||||
renderer.add_to_context(context.key.name, true);
|
||||
});
|
||||
});
|
||||
const_tags.forEach(const_tag => {
|
||||
const_tag.contexts.forEach(context => {
|
||||
if (context.type !== 'DestructuredVariable') return;
|
||||
renderer.add_to_context(context.key.name, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
export default {
|
||||
async test({ assert, component, target }) {
|
||||
await Promise.resolve();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>propA: 3</p>
|
||||
<p>propB: 7</p>
|
||||
<p>num: 3</p>
|
||||
<p>rest: {"prop3":{"prop9":9,"prop10":10}}</p>
|
||||
<p>propZ: 5</p>
|
||||
<p>propY: 6</p>
|
||||
<p>rest: {"propX":7,"propW":8}</p>
|
||||
`
|
||||
);
|
||||
|
||||
await (component.object = Promise.resolve({ prop1: 'one', prop2: 'two', prop3: { prop7: 'seven' }, prop4: { prop10: 'ten' }}));
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>propA: seven</p>
|
||||
<p>propB: ten</p>
|
||||
<p>num: 5</p>
|
||||
<p>rest: {"prop1":"one","prop2":"two"}</p>
|
||||
<p>propZ: 5</p>
|
||||
<p>propY: 6</p>
|
||||
<p>rest: {"propX":7,"propW":8}</p>
|
||||
`
|
||||
);
|
||||
}
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
<script>
|
||||
export let object = Promise.resolve({ prop1: { prop4: 2, prop5: 3 }, prop2: { prop6: 5, prop7: 6, prop8: 7 }, prop3: { prop9: 9, prop10: 10 } });
|
||||
const objectReject = Promise.reject({ propZ: 5, propY: 6, propX: 7, propW: 8 });
|
||||
|
||||
let num = 1;
|
||||
const prop = 'prop';
|
||||
</script>
|
||||
|
||||
{#await object then { [`prop${num++}`]: { [`prop${num + 3}`]: propA }, [`prop${num++}`]: { [`prop${num + 5}`]: propB }, ...rest }}
|
||||
<p>propA: {propA}</p>
|
||||
<p>propB: {propB}</p>
|
||||
<p>num: {num}</p>
|
||||
<p>rest: {JSON.stringify(rest)}</p>
|
||||
{/await}
|
||||
|
||||
{#await objectReject then value}
|
||||
resolved
|
||||
{:catch { [`${prop}Z`]: propZ, [`${prop}Y`]: propY, ...rest }}
|
||||
<p>propZ: {propZ}</p>
|
||||
<p>propY: {propY}</p>
|
||||
<p>rest: {JSON.stringify(rest)}</p>
|
||||
{/await}
|
||||
|
@ -0,0 +1,20 @@
|
||||
export default {
|
||||
html: `
|
||||
<p>4, 12, 60</p>
|
||||
`,
|
||||
|
||||
async test({ component, target, assert }) {
|
||||
component.permutation = [2, 3, 1];
|
||||
await (component.promise1 = Promise.resolve({length: 1, width: 2, height: 3}));
|
||||
try {
|
||||
await (component.promise2 = Promise.reject({length: 97, width: 98, height: 99}));
|
||||
} catch (e) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<p>2, 11, 2</p>
|
||||
<p>9506, 28811, 98</p>
|
||||
`);
|
||||
}
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
<script>
|
||||
export let promise1 = {length: 5, width: 3, height: 4};
|
||||
export let promise2 = {length: 12, width: 5, height: 13};
|
||||
export let permutation = [1, 2, 3];
|
||||
|
||||
function calculate(length, width, height) {
|
||||
return {
|
||||
'1-Dimensions': [length, width, height],
|
||||
'2-Dimensions': [length * width, width * height, length * height],
|
||||
'3-Dimensions': [length * width * height, length + width + height, length * width + width * height + length * height]
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await promise1 then { length, width, height }}
|
||||
{@const [a, b, c] = permutation}
|
||||
{@const { [`${a}-Dimensions`]: { [c - 1]: first }, [`${b}-Dimensions`]: { [b - 1]: second }, [`${c}-Dimensions`]: { [a - 1]: third } } = calculate(length, width, height) }
|
||||
<p>{first}, {second}, {third}</p>
|
||||
{/await}
|
||||
|
||||
{#await promise2 catch { length, width, height }}
|
||||
{@const [a, b, c] = permutation}
|
||||
{@const { [`${a}-Dimensions`]: { [c - 1]: first }, [`${b}-Dimensions`]: { [b - 1]: second }, [`${c}-Dimensions`]: { [a - 1]: third } } = calculate(length, width, height) }
|
||||
<p>{first}, {second}, {third}</p>
|
||||
{/await}
|
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
html: `
|
||||
<button>6, 12, 8, 24</button>
|
||||
<button>45, 35, 63, 315</button>
|
||||
<button>60, 48, 80, 480</button>
|
||||
`,
|
||||
|
||||
async test({ component, target, assert }) {
|
||||
component.boxes = [{ length: 10, width: 20, height: 30 }];
|
||||
|
||||
assert.htmlEqual(target.innerHTML,
|
||||
'<button>200, 600, 300, 6000</button>'
|
||||
);
|
||||
}
|
||||
};
|
@ -0,0 +1,42 @@
|
||||
<script>
|
||||
export let boxes = [
|
||||
{length: 2, width: 3, height: 4},
|
||||
{length: 9, width: 5, height: 7},
|
||||
{length: 10, width: 6, height: 8}
|
||||
];
|
||||
|
||||
function calculate(length, width, height) {
|
||||
return {
|
||||
twoDimensions: {
|
||||
bottomArea: length * width,
|
||||
sideArea1: width * height,
|
||||
sideArea2: length * height
|
||||
},
|
||||
threeDimensions: {
|
||||
volume: length * width * height
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export let dimension = 'Dimensions';
|
||||
function changeDimension() {
|
||||
dimension = 'DIMENSIONS';
|
||||
}
|
||||
|
||||
let area = 'Area';
|
||||
</script>
|
||||
|
||||
{#each boxes as { length, width, height }}
|
||||
{@const {
|
||||
[`two${dimension}`]: {
|
||||
i = 1,
|
||||
[`bottom${area}`]: bottom,
|
||||
[`side${area}${i++}`]: sideone,
|
||||
[`side${area}${i++}`]: sidetwo
|
||||
},
|
||||
[`three${dimension}`]: {
|
||||
volume
|
||||
}
|
||||
} = calculate(length, width, height)}
|
||||
<button on:click={changeDimension}>{bottom}, {sideone}, {sidetwo}, {volume}</button>
|
||||
{/each}
|
@ -0,0 +1,24 @@
|
||||
export default {
|
||||
props: {
|
||||
array: [
|
||||
[1, 2, 3, 4, 5],
|
||||
[6, 7, 8],
|
||||
[9, 10, 11, 12],
|
||||
[13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
|
||||
]
|
||||
},
|
||||
|
||||
html: `
|
||||
<p>First: 1, Half: 3, Last: 5, Length: 5</p>
|
||||
<p>First: 6, Half: 7, Last: 8, Length: 3</p>
|
||||
<p>First: 9, Half: 11, Last: 12, Length: 4</p>
|
||||
<p>First: 13, Half: 18, Last: 22, Length: 10</p>
|
||||
`,
|
||||
|
||||
test({ assert, component, target }) {
|
||||
component.array = [[23, 24, 25, 26, 27, 28, 29]];
|
||||
assert.htmlEqual( target.innerHTML, `
|
||||
<p>First: 23, Half: 26, Last: 29, Length: 7</p>
|
||||
`);
|
||||
}
|
||||
};
|
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let array;
|
||||
</script>
|
||||
|
||||
{#each array as { 0: first, length, [length - 1]: last, [Math.floor(length / 2)]: half }}
|
||||
<p>First: {first}, Half: {half}, Last: {last}, Length: {length}</p>
|
||||
{/each}
|
@ -0,0 +1,26 @@
|
||||
export default {
|
||||
props: {
|
||||
firstString: 'cats',
|
||||
secondString: 'dogs',
|
||||
objectsArray: [
|
||||
{ dogs: 'woof', cats: 'meow', stac: 'stack', DOGS: 'WOOF' },
|
||||
{ dogs: 'A German sheppard', cats: 'A tailless cat', stac: 'A jenga tower', DOGS: 'A GERMAN SHEPPARD' },
|
||||
{ dogs: 'dogs', cats: 'cats', stac: 'stac', DOGS: 'DOGS' }
|
||||
]
|
||||
},
|
||||
|
||||
html: `
|
||||
<p>cats: meow</p>
|
||||
<p>dogs: woof</p>
|
||||
<p>stac: stack</p>
|
||||
<p>DOGS: WOOF</p>
|
||||
<p>cats: A tailless cat</p>
|
||||
<p>dogs: A German sheppard</p>
|
||||
<p>stac: A jenga tower</p>
|
||||
<p>DOGS: A GERMAN SHEPPARD</p>
|
||||
<p>cats: cats</p>
|
||||
<p>dogs: dogs</p>
|
||||
<p>stac: stac</p>
|
||||
<p>DOGS: DOGS</p>
|
||||
`
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
export let objectsArray;
|
||||
export let firstString;
|
||||
export let secondString;
|
||||
</script>
|
||||
|
||||
{#each objectsArray as { [firstString]: firstProp, [secondString]: secondProp, [firstString.split('').reverse().join('')]: reverseFirst, [secondString.toUpperCase()]: upperSecond } }
|
||||
<p>{firstString}: {firstProp}</p>
|
||||
<p>{secondString}: {secondProp}</p>
|
||||
<p>{firstString.split('').reverse().join('')}: {reverseFirst}</p>
|
||||
<p>{secondString.toUpperCase()}: {upperSecond}</p>
|
||||
{/each}
|
Loading…
Reference in new issue