} from '@vue/runtime-dom'
import { type Block, isBlock } from './block'
import { pauseTracking, proxyRefs, resetTracking } from '@vue/reactivity'
-import { EMPTY_OBJ, isFunction, isString } from '@vue/shared'
+import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
import {
type RawProps,
getPropsProxyHandlers,
dynamicSlotsProxyHandlers,
getSlot,
} from './componentSlots'
-import { insert } from './dom/node'
-import { hmrRerender } from './hmr'
+import { insert, remove } from './dom/node'
+import { hmrReload, hmrRerender } from './hmr'
export { currentInstance } from '@vue/runtime-dom'
// HMR
registerHMR(instance)
instance.hmrRerender = hmrRerender.bind(null, instance)
+ instance.hmrReload = hmrReload.bind(null, instance)
}
} else {
// in prod result can only be block
uid: number
type: VaporComponent
parent: GenericComponentInstance | null
+ children: VaporComponentInstance[] // TODO handle vdom children
appContext: GenericAppContext
block: Block
setupState?: Record<string, any>
devtoolsRawSetupState?: any
hmrRerender?: () => void
+ hmrReload?: () => void
propsOptions?: NormalizedPropsOptions
emitsOptions?: ObjectEmitsOptions | null
this.uid = nextUid()
this.type = comp
this.parent = currentInstance // TODO proper parent source when inside vdom instance
- this.appContext = currentInstance
- ? currentInstance.appContext
- : emptyContext
+ this.children = []
+
+ if (currentInstance) {
+ if (isVaporComponent(currentInstance)) {
+ currentInstance.children.push(this)
+ }
+ this.appContext = currentInstance.appContext
+ this.provides = currentInstance.provides
+ this.ids = currentInstance.ids
+ } else {
+ this.appContext = emptyContext
+ this.provides = Object.create(this.appContext.provides)
+ this.ids = ['', 0, 0]
+ }
this.block = null! // to be set
this.scope = new EffectScope(true)
this.emit = emit.bind(null, this)
- this.provides = currentInstance
- ? currentInstance.provides
- : Object.create(this.appContext.provides)
this.refs = EMPTY_OBJ
- this.ids = currentInstance ? currentInstance.ids : ['', 0, 0]
this.emitted = this.exposed = this.propsDefaults = this.suspense = null
this.isMounted =
this.isUnmounted =
return el
}
+
+export function mountComponent(
+ instance: VaporComponentInstance,
+ parent: ParentNode,
+ anchor: Node | null | 0,
+): void {
+ if (!instance.isMounted) {
+ if (instance.bm) invokeArrayFns(instance.bm)
+ insert(instance.block, parent, anchor)
+ // queuePostFlushCb(() => {
+ if (instance.m) invokeArrayFns(instance.m)
+ instance.isMounted = true
+ // })
+ } else {
+ insert(instance.block, parent, anchor)
+ }
+}
+
+export function unmountComponent(
+ instance: VaporComponentInstance,
+ parent: ParentNode,
+): void {
+ if (instance.isMounted && !instance.isUnmounted) {
+ if (instance.bum) invokeArrayFns(instance.bum)
+ // TODO invoke unmount recursively for children
+ remove(instance.block, parent)
+ // queuePostFlushCb(() => {
+ if (instance.um) invokeArrayFns(instance.um)
+ instance.isUnmounted = true
+ // })
+ }
+}
-import { invokeArrayFns, isArray } from '@vue/shared'
+import { isArray } from '@vue/shared'
import { renderEffect } from '../renderEffect'
import { setText } from './prop'
-import { type Block, normalizeBlock } from '../block'
-import { isVaporComponent } from '../component'
+import type { Block } from '../block'
+import {
+ isVaporComponent,
+ mountComponent,
+ unmountComponent,
+} from '../component'
export function insert(
block: Block,
if (block instanceof Node) {
parent.insertBefore(block, anchor === 0 ? parent.firstChild : anchor)
} else if (isVaporComponent(block)) {
- if (!block.isMounted) {
- if (block.bm) invokeArrayFns(block.bm)
- insert(block.block, parent, anchor)
- if (block.m) invokeArrayFns(block.m)
- block.isMounted = true
- } else {
- insert(block.block, parent, anchor)
- }
+ mountComponent(block, parent, anchor)
} else if (isArray(block)) {
for (let i = 0; i < block.length; i++) {
insert(block[i], parent, anchor)
for (const b of blocks) insert(b, parent, 0)
}
-// TODO optimize
+// TODO invoke unmount recursive
export function remove(block: Block, parent: ParentNode): void {
- const nodes = normalizeBlock(block)
- for (let i = 0; i < nodes.length; i++) {
- parent.removeChild(nodes[i])
+ if (block instanceof Node) {
+ parent.removeChild(block)
+ } else if (isVaporComponent(block)) {
+ unmountComponent(block, parent)
+ } else if (isArray(block)) {
+ for (let i = 0; i < block.length; i++) {
+ remove(block[i], parent)
+ }
+ } else {
+ // fragment
+ remove(block.nodes, parent)
+ if (block.anchor) remove(block.anchor, parent)
}
}
-// TODO optimize
export function createTextNode(values?: any[] | (() => any[])): Text {
// eslint-disable-next-line no-restricted-globals
const node = document.createTextNode('')