fix: account for proxified instance when updating `bind:this` (#18147)

Fixes #18145

I wonder why nulling happens after updating `bind:this` but not before,
which would fix the issue as well, though not as efficiently.

### Before submitting the PR, please make sure you do the following

- [x] It's really useful if your PR references an issue where it is
discussed ahead of time. In many cases, features are absent for a
reason. For large changes, please create an RFC:
https://github.com/sveltejs/rfcs
- [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
- [x] This message body should clearly illustrate what problems it
solves.
- [x] Ideally, include a test that fails without this PR but passes with
it.
- [x] If this PR changes code within `packages/svelte/src`, add a
changeset (`npx changeset`).

### Tests and linting

- [x] Run the tests with `pnpm test` and lint the project with `pnpm
lint`
pull/18163/head
7nik 3 months ago committed by GitHub
parent bd29b9ef2b
commit ada3076967
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: account for proxified instance when updating `bind:this`

@ -40,7 +40,7 @@ export function bind_this(element_or_component = {}, update, get_value, get_part
parts = get_parts?.() || [];
untrack(() => {
if (element_or_component !== get_value(...parts)) {
if (!is_bound_this(get_value(...parts), element_or_component)) {
update(element_or_component, ...parts);
// If this is an effect rerun (cause: each block context changes), then nullify the binding at
// the previous position if it isn't already taken over by a different effect.

@ -0,0 +1,5 @@
<script>
const props = $props();
// svelte-ignore state_referenced_locally
export const name = props.name;
</script>

@ -0,0 +1,22 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target, logs }) {
const btn = target.querySelector('button');
flushSync(() => {
btn?.click();
});
flushSync(() => {
btn?.click();
});
assert.deepEqual(logs, [
{},
{ 0: { name: 'Row 0' } },
{ 0: { name: 'Row 0' }, 1: { name: 'Row 1' } }
]);
}
});

@ -0,0 +1,16 @@
<script>
import Row from "./Component.svelte";
const nums = $state([]);
const rows = $derived(nums.map(n => ({id: n, name: `Row ${n}` })));
const refs = $state({});
$effect(() => {
console.log({...refs});
})
</script>
<button onclick={() => nums.push(nums.length)}>Add</button>
{#each rows as row (row.id)}
<Row name={row.name} bind:this={refs[row.id]} />
{/each}
Loading…
Cancel
Save