Skip to content

Commit 0598f2b

Browse files
fix: reset reset_element in render to prevent runtime error (#13669)
1 parent 9f930f4 commit 0598f2b

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

.changeset/witty-shirts-confess.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: reset `reset_element` in `render` to prevent runtime error

packages/svelte/src/internal/server/dev.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ function print_error(payload, parent, child) {
5353
}
5454

5555
export function reset_elements() {
56+
let old_parent = parent;
5657
parent = null;
58+
return () => {
59+
parent = old_parent;
60+
};
5761
}
5862

5963
/**

packages/svelte/src/internal/server/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ export function render(component, options = {}) {
101101
on_destroy = [];
102102
payload.out += BLOCK_OPEN;
103103

104+
let reset_reset_element;
105+
104106
if (DEV) {
105107
// prevent parent/child element state being corrupted by a bad render
106-
reset_elements();
108+
reset_reset_element = reset_elements();
107109
}
108110

109111
if (options.context) {
@@ -118,6 +120,10 @@ export function render(component, options = {}) {
118120
pop();
119121
}
120122

123+
if (reset_reset_element) {
124+
reset_reset_element();
125+
}
126+
121127
payload.out += BLOCK_CLOSE;
122128
for (const cleanup of on_destroy) cleanup();
123129
on_destroy = prev_on_destroy;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let count = $state(0);
3+
</script>
4+
5+
<button onclick={() => (count += 1)}>
6+
clicks: {count}
7+
</button>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
props: {
6+
browser: true
7+
},
8+
9+
server_props: {
10+
browser: false
11+
},
12+
compileOptions: {
13+
dev: true
14+
},
15+
html: `<div><div><button>clicks: 0</button></div></div>`,
16+
17+
test({ target, assert }) {
18+
const button = target.querySelector('button');
19+
20+
flushSync(() => button?.click());
21+
assert.htmlEqual(target.innerHTML, `<div><div><button>clicks: 1</button></div></div>`);
22+
}
23+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script>
2+
import { createRawSnippet, hydrate } from 'svelte';
3+
import { render } from 'svelte/server';
4+
import Child from './Child.svelte';
5+
6+
let { browser } = $props();
7+
8+
let count = $state(0);
9+
10+
const hello = createRawSnippet((count) => ({
11+
render: () => `
12+
<div>${browser ? '' : render(Child).body}</div>
13+
`,
14+
setup(target) {
15+
hydrate(Child, { target })
16+
}
17+
}));
18+
</script>
19+
20+
<div>
21+
{@render hello()}
22+
</div>

0 commit comments

Comments
 (0)