]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: vapor hmr rerender
authorEvan You <evan@vuejs.org>
Sun, 8 Dec 2024 09:20:34 +0000 (17:20 +0800)
committerEvan You <evan@vuejs.org>
Sun, 8 Dec 2024 09:20:34 +0000 (17:20 +0800)
packages/runtime-core/src/component.ts
packages/runtime-core/src/hmr.ts
packages/runtime-core/src/index.ts
packages/runtime-vapor/src/block.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/hmr.ts [new file with mode: 0644]

index f9dae3d2121aa2d285ac9b37d720379fef24f865..3c69ebce1f775a6b25b9d3bb3462ca5b5d5301a6 100644 (file)
@@ -381,6 +381,17 @@ export interface GenericComponentInstance {
   // exposed properties via expose()
   exposed: Record<string, any> | null
 
+  /**
+   * setup related
+   * @internal
+   */
+  setupState?: Data
+  /**
+   * devtools access to additional info
+   * @internal
+   */
+  devtoolsRawSetupState?: any
+
   // lifecycle
   isMounted: boolean
   isUnmounted: boolean
@@ -473,6 +484,10 @@ export interface GenericComponentInstance {
    * @internal
    */
   [LifecycleHooks.SERVER_PREFETCH]?: LifecycleHook<() => Promise<unknown>>
+  /**
+   * @internal vapor only
+   */
+  hmrRerender?: () => void
 }
 
 /**
@@ -584,11 +599,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance {
    * @internal
    */
   setupState: Data
-  /**
-   * devtools access to additional info
-   * @internal
-   */
-  devtoolsRawSetupState?: any
 
   // main proxy that serves as the public instance (`this`)
   proxy: ComponentPublicInstance | null
index 643f8ffff28707f66d4d62e49a8a9d0b43044e16..2846c02228e1abcfdfc95f8d9be93c75a01cbcba 100644 (file)
@@ -96,7 +96,8 @@ function rerender(id: string, newRender?: Function): void {
     // this flag forces child components with slot content to update
     isHmrUpdating = true
     if (instance.vapor) {
-      // TODO
+      // @ts-expect-error TODO
+      instance.hmrRerender()
     } else {
       const i = instance as ComponentInternalInstance
       i.renderCache = []
index eb5f44896a8e773d45c9274a07983eba20f67131..8aabcd3acd0f65c576cc3814962e676d3fa343d8 100644 (file)
@@ -508,3 +508,4 @@ export {
   type AppUnmountFn,
 } from './apiCreateApp'
 export { currentInstance, setCurrentInstance } from './componentCurrentInstance'
+export { registerHMR, unregisterHMR } from './hmr'
index 570f1037f9e46d5fab5f2930ddf869dcb2bb482c..582ca187b107950c2347a732aed9048980c882d9 100644 (file)
@@ -40,6 +40,7 @@ export class DynamicFragment extends Fragment {
     if (this.scope) {
       this.scope.off()
       parent && remove(this.nodes, parent)
+      // TODO lifecycle unmount
     }
 
     if (render) {
index 488999a8c2afb8a8b0be4c403797d36043570c36..69f4a7bb6b86fc93821d54533a2c5b9384e60c4c 100644 (file)
@@ -14,6 +14,7 @@ import {
   nextUid,
   popWarningContext,
   pushWarningContext,
+  registerHMR,
   setCurrentInstance,
   warn,
 } from '@vue/runtime-dom'
@@ -40,6 +41,7 @@ import {
   getSlot,
 } from './componentSlots'
 import { insert } from './dom/node'
+import { hmrRerender } from './hmr'
 
 export { currentInstance } from '@vue/runtime-dom'
 
@@ -139,15 +141,13 @@ export function createComponent(
       )
       instance.block = []
     } else {
-      instance.setupState = setupResult
-      instance.block = component.render.call(
-        null,
-        proxyRefs(setupResult),
-        instance.props,
-        instance.emit,
-        instance.attrs,
-        instance.slots,
-      )
+      instance.devtoolsRawSetupState = setupResult
+      instance.setupState = proxyRefs(setupResult)
+      devRender(instance)
+
+      // HMR
+      registerHMR(instance)
+      instance.hmrRerender = hmrRerender.bind(null, instance)
     }
   } else {
     // in prod result can only be block
@@ -177,6 +177,20 @@ export function createComponent(
   return instance
 }
 
+/**
+ * dev only
+ */
+export function devRender(instance: VaporComponentInstance): void {
+  instance.block = instance.type.render!.call(
+    null,
+    instance.setupState,
+    instance.props,
+    instance.emit,
+    instance.attrs,
+    instance.slots,
+  )
+}
+
 const emptyContext: GenericAppContext = {
   app: null as any,
   config: {},
@@ -238,6 +252,8 @@ export class VaporComponentInstance implements GenericComponentInstance {
 
   // dev only
   setupState?: Record<string, any>
+  devtoolsRawSetupState?: any
+  hmrRerender?: () => void
   propsOptions?: NormalizedPropsOptions
   emitsOptions?: ObjectEmitsOptions | null
 
diff --git a/packages/runtime-vapor/src/hmr.ts b/packages/runtime-vapor/src/hmr.ts
new file mode 100644 (file)
index 0000000..51b9fa2
--- /dev/null
@@ -0,0 +1,21 @@
+import {
+  popWarningContext,
+  pushWarningContext,
+  setCurrentInstance,
+} from '@vue/runtime-core'
+import { normalizeBlock } from './block'
+import { type VaporComponentInstance, devRender } from './component'
+import { insert, remove } from './dom/node'
+
+export function hmrRerender(instance: VaporComponentInstance): void {
+  const normalized = normalizeBlock(instance.block)
+  const parent = normalized[0].parentNode!
+  const anchor = normalized[normalized.length - 1].nextSibling
+  remove(instance.block, parent)
+  const reset = setCurrentInstance(instance)
+  pushWarningContext(instance)
+  devRender(instance)
+  reset()
+  popWarningContext()
+  insert(instance.block, parent, anchor)
+}