mirror of https://github.com/vuejs/core.git
test(vapor): renderEffect
This commit is contained in:
parent
2bbb6d2fc5
commit
ec23ab9e3a
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[]) => {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue