]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
test(vapor): renderEffect
authorEvan You <evan@vuejs.org>
Mon, 9 Dec 2024 10:35:41 +0000 (18:35 +0800)
committerEvan You <evan@vuejs.org>
Mon, 9 Dec 2024 10:35:41 +0000 (18:35 +0800)
packages/runtime-vapor/__tests__/_utils.ts
packages/runtime-vapor/__tests__/renderEffect.spec.ts
packages/runtime-vapor/src/apiCreateApp.ts
packages/runtime-vapor/src/renderEffect.ts

index ce88d9a1a85d56bc41a2afdfbfd82d579ee1ddb1..a049889da68f974fd1695233c4fb41ed207ce103 100644 (file)
@@ -1,18 +1,17 @@
-import {
-  type App,
-  type Component,
-  type ComponentInternalInstance,
-  type ObjectComponent,
-  type SetupFn,
-  createVaporApp,
-  defineComponent,
-} from '../src/_old'
-import type { RawProps } from '../src/_old/componentProps'
+import { createVaporApp, defineVaporComponent } from '../src'
+import type { App } from '@vue/runtime-dom'
+import type {
+  ObjectVaporComponent,
+  VaporComponent,
+  VaporComponentInstance,
+  VaporSetupFn,
+} from '../src/component'
+import type { RawProps } from '../src/componentProps'
 
 export interface RenderContext {
-  component: Component
+  component: VaporComponent
   host: HTMLElement
-  instance: ComponentInternalInstance | undefined
+  instance: VaporComponentInstance | undefined
   app: App
   create: (props?: RawProps) => RenderContext
   mount: (container?: string | ParentNode) => RenderContext
@@ -21,7 +20,7 @@ export interface RenderContext {
   html: () => string
 }
 
-export function makeRender<C = ObjectComponent | SetupFn>(
+export function makeRender<C = ObjectVaporComponent | VaporSetupFn>(
   initHost = (): HTMLDivElement => {
     const host = document.createElement('div')
     host.setAttribute('id', 'host')
@@ -42,8 +41,8 @@ export function makeRender<C = ObjectComponent | SetupFn>(
   })
 
   function define(comp: C) {
-    const component = defineComponent(comp as any)
-    let instance: ComponentInternalInstance | undefined
+    const component = defineVaporComponent(comp as any)
+    let instance: VaporComponentInstance | undefined
     let app: App
 
     function render(
@@ -61,7 +60,7 @@ export function makeRender<C = ObjectComponent | SetupFn>(
     }
 
     function mount(container: string | ParentNode = host) {
-      instance = app.mount(container)
+      instance = app.mount(container) as any as VaporComponentInstance
       return res()
     }
 
index fb7645dc93fb834e091111f97cdb4d38442ad835..425d84990d2d06385220402fbc8306fda2395f20 100644 (file)
@@ -1,21 +1,18 @@
 import {
   EffectScope,
+  type GenericComponentInstance,
+  currentInstance,
   getCurrentScope,
   nextTick,
   onBeforeUpdate,
-  onEffectCleanup,
   onUpdated,
   ref,
-  renderEffect,
-  template,
   watchEffect,
   watchPostEffect,
   watchSyncEffect,
-} from '../src/_old'
-import {
-  type ComponentInternalInstance,
-  currentInstance,
-} from '../src/_old/component'
+} from '@vue/runtime-dom'
+import { renderEffect, template } from '../src'
+import { onEffectCleanup } from '@vue/reactivity'
 import { makeRender } from './_utils'
 
 const define = makeRender<any>()
@@ -110,8 +107,10 @@ describe('renderEffect', () => {
         })
       },
     ).render()
+
     const { change, changeRender } = instance?.setupState as any
 
+    await nextTick()
     expect(calls).toEqual(['pre 0', 'sync 0', 'renderEffect 0', 'post 0'])
     calls.length = 0
 
@@ -126,8 +125,8 @@ describe('renderEffect', () => {
     expect(calls).toEqual([
       'pre cleanup 0',
       'pre 1',
-      'beforeUpdate 1',
       'renderEffect cleanup 0',
+      'beforeUpdate 1',
       'renderEffect 1',
       'post cleanup 0',
       'post 1',
@@ -146,8 +145,8 @@ describe('renderEffect', () => {
     expect(calls).toEqual([
       'pre cleanup 1',
       'pre 2',
-      'beforeUpdate 2',
       'renderEffect cleanup 1',
+      'beforeUpdate 2',
       'renderEffect 2',
       'post cleanup 1',
       'post 2',
@@ -174,6 +173,7 @@ describe('renderEffect', () => {
       },
     ).render()
     const { update } = instance?.setupState as any
+
     await expect(async () => {
       update()
       await nextTick()
@@ -182,6 +182,9 @@ describe('renderEffect', () => {
     expect(
       '[Vue warn]: Unhandled error during execution of beforeUpdate hook',
     ).toHaveBeenWarned()
+    expect(
+      '[Vue warn]: Unhandled error during execution of component update',
+    ).toHaveBeenWarned()
   })
 
   test('errors should include the execution location with updated hook', async () => {
@@ -204,6 +207,7 @@ describe('renderEffect', () => {
     ).render()
 
     const { update } = instance?.setupState as any
+
     await expect(async () => {
       update()
       await nextTick()
@@ -217,15 +221,17 @@ describe('renderEffect', () => {
   test('should be called with the current instance and current scope', async () => {
     const source = ref(0)
     const scope = new EffectScope()
-    let instanceSnap: ComponentInternalInstance | null = null
+    let instanceSnap: GenericComponentInstance | null = null
     let scopeSnap: EffectScope | undefined = undefined
     const { instance } = define(() => {
       scope.run(() => {
         renderEffect(() => {
+          source.value
           instanceSnap = currentInstance
           scopeSnap = getCurrentScope()
         })
       })
+      return []
     }).render()
 
     expect(instanceSnap).toBe(instance)
index 4a140cf107593530589303c647704e41bd4377ae..9d6f1a5b48ff4214b87ecc23eff49164c82eaa5b 100644 (file)
@@ -34,8 +34,7 @@ export const createVaporApp: CreateAppFunction<
   ParentNode,
   VaporComponent
 > = comp => {
-  if (!_createApp)
-    _createApp = createAppAPI(mountApp, unmountApp, i => i.exposed)
+  if (!_createApp) _createApp = createAppAPI(mountApp, unmountApp, i => i)
   const app = _createApp(comp)
   const mount = app.mount
   app.mount = (container, ...args: any[]) => {
index fdd58b38b93a6912f064200381919c451806ec94..6dec684b09004594607ea60c5c903ebea4d69bbe 100644 (file)
@@ -1,4 +1,4 @@
-import { ReactiveEffect } from '@vue/reactivity'
+import { ReactiveEffect, getCurrentScope } from '@vue/reactivity'
 import {
   type SchedulerJob,
   currentInstance,
@@ -12,7 +12,8 @@ import { invokeArrayFns } from '@vue/shared'
 
 export function renderEffect(fn: () => void, noLifecycle = false): void {
   const instance = currentInstance as VaporComponentInstance
-  if (__DEV__ && !isVaporComponent(instance)) {
+  const scope = getCurrentScope()
+  if (__DEV__ && !__TEST__ && !isVaporComponent(instance)) {
     warn('renderEffect called without active vapor instance.')
   }
 
@@ -21,7 +22,9 @@ export function renderEffect(fn: () => void, noLifecycle = false): void {
     : () => {
         const prev = currentInstance
         simpleSetCurrentInstance(instance)
+        if (scope) scope.on()
         if (
+          instance &&
           instance.isMounted &&
           !instance.isUpdating &&
           (instance.bu || instance.u)
@@ -36,17 +39,19 @@ export function renderEffect(fn: () => void, noLifecycle = false): void {
         } else {
           fn()
         }
+        if (scope) scope.off()
         simpleSetCurrentInstance(prev, instance)
       }
 
   const effect = new ReactiveEffect(renderEffectFn)
   const job: SchedulerJob = effect.runIfDirty.bind(effect)
-  job.i = instance
-  job.id = instance.uid
+  if (instance) {
+    job.i = instance
+    job.id = instance.uid
+  }
   effect.scheduler = () => queueJob(job)
   effect.run()
 
-  // TODO lifecycle
   // TODO recurse handling
   // TODO measure
 }