From 436cc997406b3cbac3c1f84efb81d6b1d81befd0 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:47:34 +0200 Subject: [PATCH] fix: always pass original component to HMR wrapper (#12454) When Vite calls `hot.accept`, it passes the wrapped component, which means we're passing the HMR wrapper along as the new component. Avoid that by maintaining a reference to the original component. --- .changeset/itchy-lemons-punch.md | 5 +++++ .../phases/3-transform/client/transform-client.js | 8 +++++++- .../snapshot/samples/hmr/_expected/client/index.svelte.js | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 .changeset/itchy-lemons-punch.md diff --git a/.changeset/itchy-lemons-punch.md b/.changeset/itchy-lemons-punch.md new file mode 100644 index 0000000000..9cdc15ea4e --- /dev/null +++ b/.changeset/itchy-lemons-punch.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: always pass original component to HMR wrapper diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 9b23998349..e0e55c5337 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -418,7 +418,7 @@ export function client_component(source, analysis, options) { if (options.hmr) { const accept_fn_body = [ - b.stmt(b.call('$.set', b.id('s'), b.member(b.id('module'), b.id('default')))) + b.stmt(b.call('$.set', b.id('s'), b.member(b.id('module.default'), b.id('original')))) ]; if (analysis.css.hash) { @@ -440,8 +440,14 @@ export function client_component(source, analysis, options) { const hmr = b.block([ b.const(b.id('s'), b.call('$.source', b.id(analysis.name))), b.const(b.id('filename'), b.member(b.id(analysis.name), b.id('filename'))), + b.const(b.id('$$original'), b.id(analysis.name)), b.stmt(b.assignment('=', b.id(analysis.name), b.call('$.hmr', b.id('s')))), b.stmt(b.assignment('=', b.member(b.id(analysis.name), b.id('filename')), b.id('filename'))), + // Assign the original component to the wrapper so we can use it on hot reload patching, + // else we would call the HMR function two times + b.stmt( + b.assignment('=', b.member(b.id(analysis.name), b.id('original')), b.id('$$original')) + ), b.stmt(b.call('import.meta.hot.accept', b.arrow([b.id('module')], b.block(accept_fn_body)))) ]); diff --git a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js index 18e1185e8f..9037c5dd25 100644 --- a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js @@ -12,12 +12,14 @@ function Hmr($$anchor) { if (import.meta.hot) { const s = $.source(Hmr); const filename = Hmr.filename; + const $$original = Hmr; Hmr = $.hmr(s); Hmr.filename = filename; + Hmr.original = $$original; import.meta.hot.accept((module) => { - $.set(s, module.default); + $.set(s, module.default.original); }); }