2024-09-17 10:32:28 +08:00
|
|
|
import { EffectFlags, ReactiveEffect, getCurrentScope } from '@vue/reactivity'
|
2024-03-18 20:13:40 +08:00
|
|
|
import { invokeArrayFns } from '@vue/shared'
|
2024-04-15 02:58:32 +08:00
|
|
|
import {
|
|
|
|
|
type ComponentInternalInstance,
|
|
|
|
|
getCurrentInstance,
|
|
|
|
|
setCurrentInstance,
|
|
|
|
|
} from './component'
|
2024-09-17 10:32:28 +08:00
|
|
|
import {
|
|
|
|
|
type SchedulerJob,
|
|
|
|
|
VaporSchedulerJobFlags,
|
|
|
|
|
queueJob,
|
|
|
|
|
queuePostFlushCb,
|
|
|
|
|
} from './scheduler'
|
2024-03-18 20:13:40 +08:00
|
|
|
import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
|
|
|
|
|
import { invokeDirectiveHook } from './directives'
|
|
|
|
|
|
2024-08-09 16:56:59 +08:00
|
|
|
export function renderEffect(cb: () => void): void {
|
2024-03-18 20:13:40 +08:00
|
|
|
const instance = getCurrentInstance()
|
2024-04-16 16:55:44 +08:00
|
|
|
const scope = getCurrentScope()
|
2024-03-18 20:13:40 +08:00
|
|
|
|
2024-05-27 02:47:51 +08:00
|
|
|
if (scope) {
|
|
|
|
|
const baseCb = cb
|
|
|
|
|
cb = () => scope.run(baseCb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (instance) {
|
|
|
|
|
const baseCb = cb
|
|
|
|
|
cb = () => {
|
|
|
|
|
const reset = setCurrentInstance(instance)
|
|
|
|
|
baseCb()
|
|
|
|
|
reset()
|
|
|
|
|
}
|
|
|
|
|
job.id = instance.uid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const effect = new ReactiveEffect(() =>
|
|
|
|
|
callWithAsyncErrorHandling(cb, instance, VaporErrorCodes.RENDER_FUNCTION),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
effect.scheduler = () => queueJob(job)
|
|
|
|
|
if (__DEV__ && instance) {
|
|
|
|
|
effect.onTrack = instance.rtc
|
|
|
|
|
? e => invokeArrayFns(instance.rtc!, e)
|
|
|
|
|
: void 0
|
|
|
|
|
effect.onTrigger = instance.rtg
|
|
|
|
|
? e => invokeArrayFns(instance.rtg!, e)
|
|
|
|
|
: void 0
|
|
|
|
|
}
|
|
|
|
|
effect.run()
|
|
|
|
|
|
|
|
|
|
function job() {
|
2024-03-18 20:13:40 +08:00
|
|
|
if (!(effect.flags & EffectFlags.ACTIVE) || !effect.dirty) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 02:47:51 +08:00
|
|
|
const reset = instance && setCurrentInstance(instance)
|
|
|
|
|
|
2024-05-12 19:09:31 +08:00
|
|
|
if (instance && instance.isMounted && !instance.isUpdating) {
|
2024-03-18 20:13:40 +08:00
|
|
|
instance.isUpdating = true
|
|
|
|
|
|
2024-05-27 02:47:51 +08:00
|
|
|
const { bu, u, scope } = instance
|
|
|
|
|
const { dirs } = scope
|
2024-03-18 20:13:40 +08:00
|
|
|
// beforeUpdate hook
|
|
|
|
|
if (bu) {
|
|
|
|
|
invokeArrayFns(bu)
|
|
|
|
|
}
|
|
|
|
|
if (dirs) {
|
2024-05-27 02:47:51 +08:00
|
|
|
invokeDirectiveHook(instance, 'beforeUpdate', scope)
|
2024-03-18 20:13:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
effect.run()
|
|
|
|
|
|
2024-04-19 16:19:56 +08:00
|
|
|
queuePostFlushCb(() => {
|
2024-03-18 20:13:40 +08:00
|
|
|
instance.isUpdating = false
|
2024-05-27 02:47:51 +08:00
|
|
|
const reset = setCurrentInstance(instance)
|
2024-03-18 20:13:40 +08:00
|
|
|
if (dirs) {
|
2024-05-27 02:47:51 +08:00
|
|
|
invokeDirectiveHook(instance, 'updated', scope)
|
2024-03-18 20:13:40 +08:00
|
|
|
}
|
|
|
|
|
// updated hook
|
|
|
|
|
if (u) {
|
2024-04-19 16:19:56 +08:00
|
|
|
queuePostFlushCb(u)
|
2024-03-18 20:13:40 +08:00
|
|
|
}
|
2024-05-27 02:47:51 +08:00
|
|
|
reset()
|
2024-03-18 20:13:40 +08:00
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
effect.run()
|
|
|
|
|
}
|
2024-04-16 16:55:44 +08:00
|
|
|
|
2024-05-27 02:47:51 +08:00
|
|
|
reset && reset()
|
2024-04-21 20:30:47 +08:00
|
|
|
}
|
2024-03-18 20:13:40 +08:00
|
|
|
}
|
2024-04-15 02:58:32 +08:00
|
|
|
|
|
|
|
|
export function firstEffect(
|
|
|
|
|
instance: ComponentInternalInstance,
|
|
|
|
|
fn: () => void,
|
2024-08-09 16:56:59 +08:00
|
|
|
): void {
|
2024-04-15 02:58:32 +08:00
|
|
|
const effect = new ReactiveEffect(fn)
|
|
|
|
|
const job: SchedulerJob = () => effect.run()
|
2024-09-17 10:32:28 +08:00
|
|
|
job.flags! |= VaporSchedulerJobFlags.PRE
|
2024-04-15 02:58:32 +08:00
|
|
|
job.id = instance.uid
|
|
|
|
|
effect.scheduler = () => queueJob(job)
|
|
|
|
|
effect.run()
|
|
|
|
|
}
|