@ -1,23 +1,25 @@
/** @import { Source, Effect, TemplateNode } from '#client' */
/** @import { Effect, TemplateNode } from '#client' */
import { FILENAME , HMR } from '../../../constants.js' ;
import { EFFECT _TRANSPARENT } from '#client/constants' ;
import { hydrate _node , hydrating } from '../dom/hydration.js' ;
import { block , branch , destroy _effect } from '../reactivity/effects.js' ;
import { s ource } from '../reactivity/sources.js' ;
import { s et, s ource } from '../reactivity/sources.js' ;
import { set _should _intro } from '../render.js' ;
import { get } from '../runtime.js' ;
/ * *
* @ template { ( anchor : Comment , props : any ) => any } Component
* @ param { Component } original
* @ param { ( ) => Source < Component > } get _source
* @ param { Component } fn
* /
export function hmr ( original , get _source ) {
export function hmr ( fn ) {
const current = source ( fn ) ;
/ * *
* @ param { TemplateNode } anchor
* @ param { any } props
* /
function wrapper ( anchor , props ) {
let component = { } ;
let instance = { } ;
/** @type {Effect} */
@ -26,8 +28,9 @@ export function hmr(original, get_source) {
let ran = false ;
block ( ( ) => {
const source = get _source ( ) ;
const component = get ( source ) ;
if ( component === ( component = get ( current ) ) ) {
return ;
}
if ( effect ) {
// @ts-ignore
@ -62,16 +65,24 @@ export function hmr(original, get_source) {
}
// @ts-expect-error
wrapper [ FILENAME ] = original [ FILENAME ] ;
wrapper [ FILENAME ] = fn [ FILENAME ] ;
// @ts-ignore
wrapper [ HMR ] = {
// When we accept an update, we set the original source to the new component
original ,
// The `get_source` parameter reads `wrapper[HMR].source`, but in the `accept`
// function we always replace it with `previous[HMR].source`, which in practice
// means we only ever update the original
source : source ( original )
fn ,
current ,
update : ( /** @type {any} */ incoming ) => {
// This logic ensures that the first version of the component is the one
// whose update function and therefore block effect is preserved across updates.
// If we don't do this dance and instead just use `incoming` as the new component
// and then update, we'll create an ever-growing stack of block effects.
// Trigger the original block effect
set ( wrapper [ HMR ] . current , incoming [ HMR ] . fn ) ;
// Replace the incoming source with the original one
incoming [ HMR ] . current = wrapper [ HMR ] . current ;
}
} ;
return wrapper ;