mirror of https://github.com/sveltejs/svelte
fix: ensure proper HMR updates for dynamic components (#18079)
The BranchManager in `branches.js` does create a temporary anchor when creating a new branch offscreen, and deletes it once the branch is committed. Normally this is fine, but the combination of HMR and dynamic components leads to a bug: Since `svelte-component.js` passes the temporary anchor along to the component it generates, which is the HMR wrapper, this wrapper will have an obsolete, disconnected anchor on updates, leading to the content disappearing. The fix is to add a dev-only symbol which we set on the original (then obsolete) anchor to tell about the updated anchor that should be used for HMR updates. Fixes https://github.com/sveltejs/kit/issues/14699 Fixes #17211pull/17666/merge
parent
a4ce776070
commit
7be1a0247f
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: ensure proper HMR updates for dynamic components
|
||||
@ -0,0 +1 @@
|
||||
component
|
||||
@ -0,0 +1,30 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { HMR } from 'svelte/internal/client';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true,
|
||||
hmr: true
|
||||
},
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [btn] = target.querySelectorAll('button');
|
||||
|
||||
btn.click();
|
||||
flushSync();
|
||||
assert.htmlEqual(target.innerHTML, `<button>show</button> component`);
|
||||
|
||||
// Simulate HMR swap on the child component.
|
||||
const hidden = './_output/client/Component' + '.svelte.js';
|
||||
const mod = await import(/* vite-ignore */ hidden);
|
||||
const hmr_data = mod.default[HMR];
|
||||
const fake_incoming = {
|
||||
// Fake a new component, else HMR source's equality check will ignore the update
|
||||
[HMR]: { fn: /** @param {any} args */ (...args) => hmr_data.fn(...args), current: null }
|
||||
};
|
||||
hmr_data.update(fake_incoming);
|
||||
flushSync();
|
||||
assert.htmlEqual(target.innerHTML, `<button>show</button> component`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import Component from "./Component.svelte";
|
||||
|
||||
let C = $state(null);
|
||||
</script>
|
||||
|
||||
<button onclick={() => C = Component}>show</button>
|
||||
|
||||
<C />
|
||||
Loading…
Reference in new issue