Skip to content

Commit ad0b58e

Browse files
fix: move ownership validation into async component body (#16449)
* fix: move ownership validation into async component body * add test --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 63cbe21 commit ad0b58e

File tree

5 files changed

+53
-6
lines changed

5 files changed

+53
-6
lines changed

.changeset/healthy-carpets-deny.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: move ownership validation into async component body

packages/svelte/src/compiler/phases/3-transform/client/transform-client.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ export function client_component(analysis, options) {
364364
: b.stmt(b.call('$.init', analysis.immutable ? b.true : undefined))
365365
]);
366366

367+
if (analysis.needs_mutation_validation) {
368+
component_block.body.unshift(
369+
b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props')))
370+
);
371+
}
372+
367373
const should_inject_context =
368374
dev ||
369375
analysis.needs_context ||
@@ -434,12 +440,6 @@ export function client_component(analysis, options) {
434440
);
435441
}
436442

437-
if (analysis.needs_mutation_validation) {
438-
component_block.body.unshift(
439-
b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props')))
440-
);
441-
}
442-
443443
// we want the cleanup function for the stores to run as the very last thing
444444
// so that it can effectively clean up the store subscription even after the user effects runs
445445
if (should_inject_context) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let { object } = $props();
3+
4+
await 1;
5+
</script>
6+
7+
<button onclick={() => object.count++}>clicks: {object.count}</button>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
compileOptions: {
6+
dev: true
7+
},
8+
9+
async test({ assert, target, warnings }) {
10+
await tick();
11+
12+
const [button] = target.querySelectorAll('button');
13+
14+
button.click();
15+
await tick();
16+
17+
assert.htmlEqual(target.innerHTML, '<button>clicks: 1</button>');
18+
assert.deepEqual(warnings, [
19+
'Mutating unbound props (`object`, at Child.svelte:7:23) is strongly discouraged. Consider using `bind:object={...}` in main.svelte (or using a callback) instead'
20+
]);
21+
}
22+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import Child from './Child.svelte';
3+
4+
let object = $state({ count: 0 });
5+
</script>
6+
7+
<svelte:boundary>
8+
<Child {object} />
9+
10+
{#snippet pending()}
11+
<p>loading...</p>
12+
{/snippet}
13+
</svelte:boundary>

0 commit comments

Comments
 (0)