Skip to content

Commit

Permalink
[fix] binding member expression should only invalidate the object, no…
Browse files Browse the repository at this point in the history
…t the member property (#7008)
  • Loading branch information
tanhauhau authored Jan 6, 2022
1 parent fb419d2 commit 9f2b5af
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 2 deletions.
24 changes: 24 additions & 0 deletions src/compiler/compile/render_dom/wrappers/Element/Binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compile/render_dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
@@ -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');
}
};
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions test/runtime/samples/binding-this-each-key/_config.js
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions test/runtime/samples/binding-this-each-key/main.svelte
Original file line number Diff line number Diff line change
@@ -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}
Original file line number Diff line number Diff line change
@@ -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);
}
};
Original file line number Diff line number Diff line change
@@ -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]]} />

0 comments on commit 9f2b5af

Please sign in to comment.