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

pull contextual deps through for member exprs in this bindings - fixes #1916

This commit is contained in:
Chris Reeves 2019-01-08 23:51:45 -05:00
parent 88b6a26a35
commit 3a7b9adc7f
4 changed files with 109 additions and 7 deletions

View File

@ -24,7 +24,8 @@ export default class BindingWrapper {
handler: { handler: {
usesContext: boolean; usesContext: boolean;
mutation: string; mutation: string;
contextual_dependencies: Set<string> contextual_dependencies: Set<string>,
snippet?: string
}; };
snippet: string; snippet: string;
initialUpdate: string; initialUpdate: string;
@ -238,9 +239,10 @@ function getEventHandler(
if (binding.node.expression.node.type === 'MemberExpression') { if (binding.node.expression.node.type === 'MemberExpression') {
return { return {
usesContext: false, usesContext: binding.node.expression.usesContext,
mutation: `${snippet} = ${value};`, mutation: `${snippet} = ${value};`,
contextual_dependencies: new Set() contextual_dependencies: binding.node.expression.contextual_dependencies,
snippet
}; };
} }

View File

@ -493,15 +493,28 @@ export default class ElementWrapper extends Wrapper {
const { handler, object } = this_binding; const { handler, object } = this_binding;
const args = [];
for (const arg of handler.contextual_dependencies) {
args.push(arg);
block.addVariable(arg, `ctx.${arg}`);
}
renderer.component.partly_hoisted.push(deindent` renderer.component.partly_hoisted.push(deindent`
function ${name}($$node) { function ${name}(${['$$node', 'check'].concat(args).join(', ')}) {
${handler.mutation} ${handler.snippet ? `if ($$node || (!$$node && ${handler.snippet} === check)) ` : ''}${handler.mutation}
$$invalidate('${object}', ${object}); $$invalidate('${object}', ${object});
} }
`); `);
block.builders.mount.addLine(`@add_binding_callback(() => ctx.${name}(${this.var}));`); block.builders.mount.addLine(`@add_binding_callback(() => ctx.${name}(${[this.var, 'null'].concat(args).join(', ')}));`);
block.builders.destroy.addLine(`ctx.${name}(null);`); block.builders.destroy.addLine(`ctx.${name}(${['null', this.var].concat(args).join(', ')});`);
block.builders.update.addLine(deindent`
if (changed.items) {
ctx.${name}(${['null', this.var].concat(args).join(', ')});
${args.map(a => `${a} = ctx.${a}`).join(', ')};
ctx.${name}(${[this.var, 'null'].concat(args).join(', ')});
}`
);
} }
} }

View File

@ -0,0 +1,59 @@
export default {
html: `<div>foo</div><div>bar</div><div>baz</div>
<span>foo</span><span>bar</span><span>baz</span>
<ul><li><p>foo</p></li><li><p>bar</p></li><li><p>baz</p></li></ul>
<ul><li><hr /></li><li><hr /></li><li><hr /></li></ul>`,
test({ assert, component, target }) {
let elems = target.querySelectorAll('div');
assert.equal(component.divs.length, 3, 'three divs are registered (unkeyed array)');
component.divs.forEach((e, i) => {
assert.equal(e, elems[i], `div ${i} is correct (unkeyed array)`);
});
elems = target.querySelectorAll('span');
assert.equal(Object.keys(component.spans).length, 3, 'three spans are registered (unkeyed object)');
component.items.forEach((e, i) => {
assert.equal(component.spans[`-${e}${i}`], elems[i], `span -${e}${i} is correct (unkeyed object)`);
});
elems = target.querySelectorAll('p');
assert.equal(component.ps.length, 3, 'three ps are registered (keyed array)');
component.ps.forEach((e, i) => {
assert.equal(e, elems[i], `p ${i} is correct (keyed array)`);
});
elems = target.querySelectorAll('hr');
assert.equal(Object.keys(component.hrs).length, 3, 'three hrs are registered (keyed object)');
component.items.forEach((e, i) => {
assert.equal(component.hrs[e], elems[i], `hr ${e} is correct (keyed object)`);
});
component.items = ['foo', 'baz'];
assert.equal(component.divs.length, 3, 'the divs array is still 3 long');
assert.equal(component.divs[2], null, 'the last div is unregistered');
assert.equal(component.ps[2], null, 'the last p is unregistered');
assert.equal(component.spans['-bar1'], null, 'the bar span is unregisterd');
assert.equal(component.hrs.bar, null, 'the bar hr is unregisterd');
elems = target.querySelectorAll('div');
component.divs.forEach((e, i) => {
assert.equal(e, elems[i], `div ${i} is still correct`);
});
elems = target.querySelectorAll('span');
component.items.forEach((e, i) => {
assert.equal(component.spans[`-${e}${i}`], elems[i], `span -${e}${i} is still correct`);
});
elems = target.querySelectorAll('p');
component.ps.forEach((e, i) => {
assert.equal(e, elems[i], `p ${i} is still correct`);
});
elems = target.querySelectorAll('hr');
component.items.forEach((e, i) => {
assert.equal(component.hrs[e], elems[i], `hr ${e} is still correct`);
});
}
};

View File

@ -0,0 +1,28 @@
<script>
export let items = ['foo', 'bar', 'baz'];
export let divs = [];
export let spans = {};
export let ps = [];
export let hrs = {};
const prefix = '-';
</script>
{#each items as item, j}
<div bind:this={divs[j]}>{item}</div>
{/each}
{#each Object.entries(items) as [ key, val ] }
<span bind:this="{spans[prefix + val + key]}">{val}</span>
{/each}
<ul>
{#each items as thing, j (thing)}
<li><p bind:this="{ps[j]}">{thing}</p></li>
{/each}
</ul>
<ul>
{#each items as sure, j (sure)}
<li><hr bind:this="{hrs[sure]}" /></li>
{/each}
</ul>