mirror of
https://github.com/sveltejs/svelte.git
synced 2024-11-30 00:46:29 +01:00
[fix] binding member expression should only invalidate the object, not the member property (#7008)
This commit is contained in:
parent
fb419d2fda
commit
9f2b5afdf7
@ -70,6 +70,30 @@ export default class BindingWrapper {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
get_update_dependencies() {
|
||||
const object = this.object;
|
||||
const dependencies = new Set<string>();
|
||||
if (this.node.expression.template_scope.names.has(object)) {
|
||||
this.node.expression.template_scope.dependencies_for_name
|
||||
.get(object)
|
||||
.forEach((name) => dependencies.add(name));
|
||||
} else {
|
||||
dependencies.add(object);
|
||||
}
|
||||
|
||||
const result = new Set(dependencies);
|
||||
dependencies.forEach((dependency) => {
|
||||
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(dependency);
|
||||
if (indirect_dependencies) {
|
||||
indirect_dependencies.forEach(indirect_dependency => {
|
||||
result.add(indirect_dependency);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
is_readonly_media_attribute() {
|
||||
return this.node.is_readonly_media_attribute();
|
||||
}
|
||||
|
@ -466,7 +466,7 @@ export default class ElementWrapper extends Wrapper {
|
||||
|
||||
binding_group.bindings.forEach(binding => {
|
||||
// TODO this is a mess
|
||||
add_to_set(dependencies, binding.get_dependencies());
|
||||
add_to_set(dependencies, binding.get_update_dependencies());
|
||||
add_to_set(contextual_dependencies, binding.handler.contextual_dependencies);
|
||||
|
||||
binding.render(block, lock);
|
||||
|
@ -12,7 +12,7 @@ export default function bind_this(component: Component, block: Block, binding: B
|
||||
const callee = block.renderer.reference(fn.name);
|
||||
|
||||
const { contextual_dependencies, mutation } = binding.handler;
|
||||
const dependencies = binding.get_dependencies();
|
||||
const dependencies = binding.get_update_dependencies();
|
||||
|
||||
const body = b`
|
||||
${mutation}
|
||||
|
@ -0,0 +1,18 @@
|
||||
// binding member expression shouldn't invalidate the property name
|
||||
export default {
|
||||
async test({ assert, component, target, window }) {
|
||||
const input = target.querySelector('input');
|
||||
assert.deepEqual(component.logs.length, 1);
|
||||
assert.equal(input.value, 'abc');
|
||||
|
||||
input.value = 'hij';
|
||||
await input.dispatchEvent(new window.Event('input'));
|
||||
|
||||
assert.deepEqual(component.values.a, 'hij');
|
||||
assert.deepEqual(component.logs.length, 1);
|
||||
|
||||
component.paths = ['b'];
|
||||
assert.deepEqual(component.logs.length, 2);
|
||||
assert.equal(input.value, 'def');
|
||||
}
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
export let values = { a: 'abc', b: 'def' };
|
||||
export let paths = ['a'];
|
||||
export let logs = [];
|
||||
|
||||
$: paths && logs.push('paths updated');
|
||||
</script>
|
||||
|
||||
<input bind:value={values[paths[0]]} />
|
10
test/runtime/samples/binding-this-each-key/_config.js
Normal file
10
test/runtime/samples/binding-this-each-key/_config.js
Normal file
@ -0,0 +1,10 @@
|
||||
export default {
|
||||
html: '<div>content</div><div>content</div><div>content</div>',
|
||||
|
||||
test({ assert, target, component }) {
|
||||
const divs = target.querySelectorAll('div');
|
||||
assert.equal(component.refs[0], divs[0]);
|
||||
assert.equal(component.refs[1], divs[1]);
|
||||
assert.equal(component.refs[2], divs[2]);
|
||||
}
|
||||
};
|
15
test/runtime/samples/binding-this-each-key/main.svelte
Normal file
15
test/runtime/samples/binding-this-each-key/main.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
export let data = [ { id: '1' }, { id: '2' }, { id: '3' } ];
|
||||
|
||||
export let refs = [];
|
||||
|
||||
// note that this is NOT data.slice().reverse()
|
||||
// as that wouldn't have triggered an infinite loop
|
||||
$: list = data.reverse();
|
||||
</script>
|
||||
|
||||
{#each list as { id }, index (id)}
|
||||
<div bind:this={refs[index]}>
|
||||
content
|
||||
</div>
|
||||
{/each}
|
@ -0,0 +1,8 @@
|
||||
// binding member expression shouldn't invalidate the property name
|
||||
export default {
|
||||
test({ assert, component, target }) {
|
||||
const div = target.querySelector('div');
|
||||
assert.equal(div, component.container.a);
|
||||
assert.deepEqual(component.logs.length, 1);
|
||||
}
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
export let container = {};
|
||||
export let paths = ['a'];
|
||||
export let logs = [];
|
||||
|
||||
$: paths && logs.push('paths updated');
|
||||
</script>
|
||||
|
||||
<div bind:this={container[paths[0]]} />
|
Loading…
Reference in New Issue
Block a user