-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
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')
})
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(
}
function mount(container: string | ParentNode = host) {
- instance = app.mount(container)
+ instance = app.mount(container) as any as VaporComponentInstance
return res()
}
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>()
})
},
).render()
+
const { change, changeRender } = instance?.setupState as any
+ await nextTick()
expect(calls).toEqual(['pre 0', 'sync 0', 'renderEffect 0', 'post 0'])
calls.length = 0
expect(calls).toEqual([
'pre cleanup 0',
'pre 1',
- 'beforeUpdate 1',
'renderEffect cleanup 0',
+ 'beforeUpdate 1',
'renderEffect 1',
'post cleanup 0',
'post 1',
expect(calls).toEqual([
'pre cleanup 1',
'pre 2',
- 'beforeUpdate 2',
'renderEffect cleanup 1',
+ 'beforeUpdate 2',
'renderEffect 2',
'post cleanup 1',
'post 2',
},
).render()
const { update } = instance?.setupState as any
+
await expect(async () => {
update()
await nextTick()
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 () => {
).render()
const { update } = instance?.setupState as any
+
await expect(async () => {
update()
await nextTick()
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)
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[]) => {
-import { ReactiveEffect } from '@vue/reactivity'
+import { ReactiveEffect, getCurrentScope } from '@vue/reactivity'
import {
type SchedulerJob,
currentInstance,
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.')
}
: () => {
const prev = currentInstance
simpleSetCurrentInstance(instance)
+ if (scope) scope.on()
if (
+ instance &&
instance.isMounted &&
!instance.isUpdating &&
(instance.bu || instance.u)
} 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
}