fix: properly add owners to function bindings

ownership-function-bindings
paoloricciuti 8 months ago
parent a00170d569
commit f341d2e731

@ -2,7 +2,11 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */
import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
import {
extract_all_identifiers_from_expression,
get_attribute_chunks,
object
} from '../../../../../utils/ast.js';
import * as b from '../../../../../utils/builders.js';
import { create_derived } from '../../utils.js';
import { build_bind_this, validate_binding } from '../shared/utils.js';
@ -220,6 +224,32 @@ export function build_component(node, component_name, context, anchor = context.
push_prop(b.get(attribute.name, [b.return(b.call(get_id))]));
push_prop(b.set(attribute.name, [b.stmt(b.call(set_id, b.id('$$value')))]));
if (dev) {
const [, get_ids] = extract_all_identifiers_from_expression(get);
for (let get_id of get_ids) {
const binding = context.state.scope.get(get_id.name);
if (
binding &&
binding.kind !== 'derived' &&
binding.kind !== 'raw_state' &&
!ownerships_effects.has(get_id.name)
) {
ownerships_effects.set(get_id.name, () => {
binding_initializers.push(
b.stmt(
b.call(
b.id('$.add_owner_effect'),
b.thunk(get_id),
b.id(component_name),
is_ignored(node, 'ownership_invalid_binding') && b.true
)
)
);
});
}
}
}
}
} else {
if (

@ -0,0 +1,5 @@
<script>
let { arr = $bindable() } = $props();
</script>
<button onclick={() => arr.push(arr.length)}></button>

@ -0,0 +1,20 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true
},
test({ target, warnings, assert }) {
const btn = target.querySelector('button');
flushSync(() => {
btn?.click();
});
assert.deepEqual(warnings, []);
flushSync(() => {
btn?.click();
});
assert.deepEqual(warnings, []);
}
});

@ -0,0 +1,10 @@
<script>
import Child from './Child.svelte';
let arr = $state([]);
let arr2 = $state([]);
let len = $derived(arr.length + arr2.length);
</script>
<Child bind:arr={() => len % 2 === 0 ? arr : arr2, (v) => {}} />
Loading…
Cancel
Save