fix: move ownership validation into async component body (#16449)

* fix: move ownership validation into async component body

* add test

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/16445/head
ComputerGuy 2 months ago committed by GitHub
parent 63cbe2108a
commit ad0b58ee96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: move ownership validation into async component body

@ -364,6 +364,12 @@ export function client_component(analysis, options) {
: b.stmt(b.call('$.init', analysis.immutable ? b.true : undefined))
]);
if (analysis.needs_mutation_validation) {
component_block.body.unshift(
b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props')))
);
}
const should_inject_context =
dev ||
analysis.needs_context ||
@ -434,12 +440,6 @@ export function client_component(analysis, options) {
);
}
if (analysis.needs_mutation_validation) {
component_block.body.unshift(
b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props')))
);
}
// we want the cleanup function for the stores to run as the very last thing
// so that it can effectively clean up the store subscription even after the user effects runs
if (should_inject_context) {

@ -0,0 +1,7 @@
<script>
let { object } = $props();
await 1;
</script>
<button onclick={() => object.count++}>clicks: {object.count}</button>

@ -0,0 +1,22 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true
},
async test({ assert, target, warnings }) {
await tick();
const [button] = target.querySelectorAll('button');
button.click();
await tick();
assert.htmlEqual(target.innerHTML, '<button>clicks: 1</button>');
assert.deepEqual(warnings, [
'Mutating unbound props (`object`, at Child.svelte:7:23) is strongly discouraged. Consider using `bind:object={...}` in main.svelte (or using a callback) instead'
]);
}
});

@ -0,0 +1,13 @@
<script>
import Child from './Child.svelte';
let object = $state({ count: 0 });
</script>
<svelte:boundary>
<Child {object} />
{#snippet pending()}
<p>loading...</p>
{/snippet}
</svelte:boundary>
Loading…
Cancel
Save