diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/AsyncLayout.svelte b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/AsyncLayout.svelte
new file mode 100644
index 0000000000..ac26e633ec
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/AsyncLayout.svelte
@@ -0,0 +1,13 @@
+
+
+
Resolving a promise here: {await Promise.resolve('ok')}
+
+
+ {@render children?.()}
+
+ {#snippet pending()}
+ loading...
+ {/snippet}
+
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/DataLayout.svelte b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/DataLayout.svelte
new file mode 100644
index 0000000000..8e2a0dc9cf
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/DataLayout.svelte
@@ -0,0 +1,11 @@
+
+
+{@render children?.()}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/Page.svelte b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/Page.svelte
new file mode 100644
index 0000000000..62368b361d
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/Page.svelte
@@ -0,0 +1 @@
+this is the child
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/RootLayout.svelte b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/RootLayout.svelte
new file mode 100644
index 0000000000..a49a739284
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/RootLayout.svelte
@@ -0,0 +1,5 @@
+
+
+{@render children?.()}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/_config.js b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/_config.js
new file mode 100644
index 0000000000..14d2e0f04c
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/_config.js
@@ -0,0 +1,30 @@
+import { settled } from 'svelte';
+import { test } from '../../test';
+
+// Regression test for https://github.com/sveltejs/kit/issues/17383
+export default test({
+ mode: ['hydrate'],
+ skip_initial_flushSync: true,
+
+ async test({ assert, target, component, mod, hydrate, logs }) {
+ const tree = mod.create_tree();
+ const { data, child } = tree;
+ tree.data = {};
+ tree.child = undefined;
+ component.tree = tree;
+ await Promise.resolve();
+
+ // Kit applies the loaded data to its existing root immediately before hydration.
+ // Do not flush these writes: the async boundary must encounter the pending batch.
+ tree.data = data;
+ tree.child = child;
+ hydrate();
+ await settled();
+
+ assert.htmlEqual(
+ target.innerHTML,
+ 'Resolving a promise here: ok
this is the child
'
+ );
+ assert.deepEqual(logs, ['root', 'child']);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/main.svelte
new file mode 100644
index 0000000000..a320f2469b
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/main.svelte
@@ -0,0 +1,94 @@
+
+
+
+
+{#snippet node(n, depth)}
+ {const Component = $derived(n.component)}
+ {const Error = $derived(n.error)}
+ {const data = $derived(n.data)}
+
+ {#snippet failed(error)}
+
+ {/snippet}
+
+
+ {#if n.child}
+
+ {@render node(n.child, depth + 1)}
+
+ {:else}
+
+ {/if}
+
+{/snippet}
+
+{@render node(tree, 0)}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/state.svelte.js b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/state.svelte.js
new file mode 100644
index 0000000000..1c34cc0974
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/async-hydration-pre-mount-writes/state.svelte.js
@@ -0,0 +1,21 @@
+export class RenderNode {
+ /** @type {any} */
+ component;
+
+ /** @type {any} */
+ error;
+
+ data = $state.raw({});
+
+ /** @type {RenderNode | undefined} */
+ child = $state.raw();
+
+ /**
+ * @param {any} component
+ * @param {any} [error]
+ */
+ constructor(component, error) {
+ this.component = component;
+ this.error = error;
+ }
+}