Skip to content

Commit

Permalink
refactor: cleaning up the code
Browse files Browse the repository at this point in the history
  • Loading branch information
LittleSound committed Jun 26, 2024
1 parent b3e07b4 commit 818ccb6
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 118 deletions.
99 changes: 36 additions & 63 deletions packages/runtime-vapor/src/apiCreateComponent.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import {
type Component,
createComponentInstance,
setCurrentInstance,
} from './component'
import { type Component, createComponentInstance } from './component'
import { setupComponent } from './apiRender'
import type { RawProps } from './componentProps'
import type { RawSlots } from './componentSlots'
import { withAttrs } from './componentAttrs'
import { getCurrentScope } from '@vue/reactivity'
import type { BlockEffectScope } from './blockEffectScope'
import {
type Directive,
type DirectiveHookName,
invokeDirectiveHook,
} from './directives'
import { setDirectiveBinding } from './directives'
import { VaporLifecycleHooks } from './enums'
import { NOOP, invokeArrayFns } from '@vue/shared'
import { scheduleLifecycleHooks } from './componentLifecycle'

export function createComponent(
comp: Component,
Expand All @@ -33,58 +25,39 @@ export function createComponent(
)
setupComponent(instance, singleRoot)

const directiveBindingsMap = (parentScope.dirs ||= new Map())
const dir: Directive = {
beforeMount: passDirectives(
VaporLifecycleHooks.BEFORE_MOUNT,
'beforeMount',
),
mounted: passDirectives(
VaporLifecycleHooks.MOUNTED,
'mounted',
() => (instance.isMounted = true),
true,
),
beforeUnmount: passDirectives(
VaporLifecycleHooks.BEFORE_UNMOUNT,
'beforeUnmount',
),
unmounted: passDirectives(
VaporLifecycleHooks.UNMOUNTED,
'unmounted',
() => (instance.isUnmounted = true),
true,
),
}
directiveBindingsMap.set(instance, [
{ dir, instance, value: null, oldValue: undefined },
])
setDirectiveBinding(
instance,
instance,
{
beforeMount: scheduleLifecycleHooks(
instance,
VaporLifecycleHooks.BEFORE_MOUNT,
'beforeMount',
),
mounted: scheduleLifecycleHooks(
instance,
VaporLifecycleHooks.MOUNTED,
'mounted',
() => (instance.isMounted = true),
true,
),
beforeUnmount: scheduleLifecycleHooks(
instance,
VaporLifecycleHooks.BEFORE_UNMOUNT,
'beforeUnmount',
),
unmounted: scheduleLifecycleHooks(
instance,
VaporLifecycleHooks.UNMOUNTED,
'unmounted',
() => (instance.isUnmounted = true),
true,
),
},
null,
undefined,
parentScope,
)

return instance

function passDirectives(
lifecycle: VaporLifecycleHooks,
directive: DirectiveHookName,
cb = NOOP,
reverse?: boolean,
) {
const hooks = reverse
? [cb, callDirHooks, callLifecycleHooks]
: [callLifecycleHooks, callDirHooks, cb]

return () => invokeArrayFns(hooks)

function callDirHooks() {
invokeDirectiveHook(instance, directive, instance.scope)
}
function callLifecycleHooks() {
// lifecycle hooks may be mounted halfway.
const lifecycleHooks = instance[lifecycle]
if (lifecycleHooks && lifecycleHooks.length) {
const reset = setCurrentInstance(instance)
instance.scope.run(() => invokeArrayFns(lifecycleHooks))
reset()
}
}
}
}
4 changes: 2 additions & 2 deletions packages/runtime-vapor/src/apiCreateFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { type Block, type Fragment, fragmentKey } from './apiRender'
import { warn } from './warning'
import { currentInstance } from './component'
import { componentKey } from './component'
import { BlockEffectScope, isRenderEffectScope } from './blockEffectScope'
import { BlockEffectScope, isBlockEffectScope } from './blockEffectScope'
import {
createChildFragmentDirectives,
invokeWithMount,
Expand Down Expand Up @@ -62,7 +62,7 @@ export const createFor = (
}

const instance = currentInstance!
if (__DEV__ && (!instance || !isRenderEffectScope(parentScope))) {
if (__DEV__ && (!instance || !isBlockEffectScope(parentScope))) {
warn('createFor() can only be used inside setup()')
}

Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-vapor/src/apiCreateIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getCurrentScope } from '@vue/reactivity'
import { createComment, createTextNode, insert, remove } from './dom/element'
import { currentInstance } from './component'
import { warn } from './warning'
import { BlockEffectScope, isRenderEffectScope } from './blockEffectScope'
import { BlockEffectScope, isBlockEffectScope } from './blockEffectScope'
import {
createChildFragmentDirectives,
invokeWithMount,
Expand Down Expand Up @@ -36,7 +36,7 @@ export const createIf = (
}

const instance = currentInstance!
if (__DEV__ && (!instance || !isRenderEffectScope(parentScope))) {
if (__DEV__ && (!instance || !isBlockEffectScope(parentScope))) {
warn('createIf() can only be used inside setup()')
}

Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-vapor/src/apiRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function mountComponent(
instance,
VaporLifecycleHooks.MOUNTED,
'mounted',
instance => (instance.isMounted = true),
() => (instance.isMounted = true),
true,
)

Expand Down Expand Up @@ -166,7 +166,7 @@ export function unmountComponent(instance: ComponentInternalInstance) {
instance,
VaporLifecycleHooks.UNMOUNTED,
'unmounted',
instance => queuePostFlushCb(() => (instance.isUnmounted = true)),
() => (instance.isUnmounted = true),
true,
)
flushPostFlushCbs()
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-vapor/src/blockEffectScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class BlockEffectScope extends EffectScope {
}
}

export function isRenderEffectScope(
export function isBlockEffectScope(
scope: EffectScope | undefined,
): scope is BlockEffectScope {
return scope instanceof BlockEffectScope
Expand Down
2 changes: 0 additions & 2 deletions packages/runtime-vapor/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ export interface ComponentInternalInstance {

provides: Data
scope: BlockEffectScope
comps: Set<ComponentInternalInstance>

rawProps: NormalizedRawProps
propsOptions: NormalizedPropsOptions
Expand Down Expand Up @@ -286,7 +285,6 @@ export function createComponentInstance(
scope: null!,
provides: parent ? parent.provides : Object.create(_appContext.provides),
type: component,
comps: new Set(),

// resolved props and emits options
rawProps: null!, // set later
Expand Down
47 changes: 27 additions & 20 deletions packages/runtime-vapor/src/componentLifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
import { invokeArrayFns } from '@vue/shared'
import { NOOP, invokeArrayFns } from '@vue/shared'
import type { VaporLifecycleHooks } from './enums'
import { type ComponentInternalInstance, setCurrentInstance } from './component'
import { queuePostFlushCb } from './scheduler'
import { type DirectiveHookName, invokeDirectiveHook } from './directives'
import { queuePostFlushCb } from './scheduler'

export function invokeLifecycle(
instance: ComponentInternalInstance,
lifecycle: VaporLifecycleHooks,
directive: DirectiveHookName,
cb?: (instance: ComponentInternalInstance) => void,
cb?: () => void,
post?: boolean,
) {
invokeArrayFns(post ? [invokeSub, invokeCurrent] : [invokeCurrent, invokeSub])
const fn = scheduleLifecycleHooks(instance, lifecycle, directive, cb, post)
return post ? queuePostFlushCb(fn) : fn()
}

function invokeCurrent() {
cb && cb(instance)
const hooks = instance[lifecycle]
if (hooks) {
const fn = () => {
const reset = setCurrentInstance(instance)
instance.scope.run(() => invokeArrayFns(hooks))
reset()
}
post ? queuePostFlushCb(fn) : fn()
}
export function scheduleLifecycleHooks(
instance: ComponentInternalInstance,
lifecycle: VaporLifecycleHooks,
directive: DirectiveHookName,
cb = NOOP,
reverse?: boolean,
) {
const hooks = reverse
? [cb, callDirHooks, callLifecycleHooks]
: [callLifecycleHooks, callDirHooks, cb]

return () => invokeArrayFns(hooks)

function callDirHooks() {
invokeDirectiveHook(instance, directive, instance.scope)
}

function invokeSub() {
instance.comps.forEach(comp =>
invokeLifecycle(comp, lifecycle, directive, cb, post),
)
function callLifecycleHooks() {
// lifecycle hooks may be mounted halfway.
const lifecycleHooks = instance[lifecycle]
if (lifecycleHooks && lifecycleHooks.length) {
const reset = setCurrentInstance(instance)
instance.scope.run(() => invokeArrayFns(lifecycleHooks))
reset()
}
}
}
23 changes: 20 additions & 3 deletions packages/runtime-vapor/src/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
} from './errorHandling'
import { queueJob, queuePostFlushCb } from './scheduler'
import { warn } from './warning'
import { type BlockEffectScope, isRenderEffectScope } from './blockEffectScope'
import { type BlockEffectScope, isBlockEffectScope } from './blockEffectScope'
import { normalizeBlock } from './dom/element'

export type DirectiveModifiers<M extends string = string> = Record<M, boolean>
Expand Down Expand Up @@ -112,8 +112,8 @@ export function withDirectives<T extends ComponentInternalInstance | Node>(
const instance = currentInstance!
const parentScope = getCurrentScope() as BlockEffectScope

if (__DEV__ && !isRenderEffectScope(parentScope)) {
warn(`Directives should be used inside of RenderEffectScope.`)
if (__DEV__ && !isBlockEffectScope(parentScope)) {
warn(`Directives should be used inside of BlockEffectScope.`)
}

const directivesMap = (parentScope.dirs ||= new Map())
Expand Down Expand Up @@ -264,3 +264,20 @@ export function createRenderingUpdateTrigger(
}
}
}

/** For internal use, set directive binding */
export function setDirectiveBinding(
instance: ComponentInternalInstance | null,
anchor: Node | ComponentInternalInstance,
dir: Directive,
value: any = null,
oldValue: any = undefined,
parentScope = getCurrentScope() as BlockEffectScope,
) {
if (__DEV__ && !isBlockEffectScope(parentScope)) {
warn('directive binding can only be added to BlockEffectScope')
}

const directiveBindingsMap = (parentScope.dirs ||= new Map())
directiveBindingsMap.set(anchor, [{ dir, instance, value, oldValue }])
}
31 changes: 8 additions & 23 deletions packages/runtime-vapor/src/directivesChildFragment.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ReactiveEffect, getCurrentScope } from '@vue/reactivity'
import { ReactiveEffect } from '@vue/reactivity'
import {
type Directive,
type DirectiveHookName,
createRenderingUpdateTrigger,
invokeDirectiveHook,
setDirectiveBinding,
} from './directives'
import { warn } from './warning'
import { type BlockEffectScope, isRenderEffectScope } from './blockEffectScope'
import { type BlockEffectScope, isBlockEffectScope } from './blockEffectScope'
import { currentInstance } from './component'
import { VaporErrorCodes, callWithErrorHandling } from './errorHandling'
import { queueJob, queuePostFlushCb } from './scheduler'
Expand All @@ -25,14 +25,8 @@ export function createChildFragmentDirectives(
) {
let isTriggered = false
const instance = currentInstance!
const parentScope = getCurrentScope() as BlockEffectScope
if (__DEV__) {
if (!isRenderEffectScope(parentScope)) {
warn('child directives can only be added to a render effect scope')
}
if (!instance) {
warn('child directives can only be added in a component')
}
if (__DEV__ && !instance) {
warn('child directives can only be added in a component')
}

const callSourceWithErrorHandling = () =>
Expand All @@ -43,22 +37,13 @@ export function createChildFragmentDirectives(
return
}

const directiveBindingsMap = (parentScope.dirs ||= new Map())
const dir: Directive = {
setDirectiveBinding(instance, anchor, {
beforeUpdate: onDirectiveBeforeUpdate,
beforeMount: () => invokeChildrenDirectives('beforeMount'),
mounted: () => invokeChildrenDirectives('mounted'),
beforeUnmount: () => invokeChildrenDirectives('beforeUnmount'),
unmounted: () => invokeChildrenDirectives('unmounted'),
}
directiveBindingsMap.set(anchor, [
{
dir,
instance,
value: null,
oldValue: undefined,
},
])
})

const effect = new ReactiveEffect(callSourceWithErrorHandling)
const triggerRenderingUpdate = createRenderingUpdateTrigger(instance, effect)
Expand Down Expand Up @@ -93,7 +78,7 @@ export function createChildFragmentDirectives(
}

export function invokeWithMount(scope: BlockEffectScope, handler?: () => any) {
if (isRenderEffectScope(scope.parent) && !scope.parent.im) {
if (isBlockEffectScope(scope.parent) && !scope.parent.im) {
return handler && handler()
}
return invokeWithDirsHooks(scope, 'mount', handler)
Expand Down

0 comments on commit 818ccb6

Please sign in to comment.