-import { fragmentKey, normalizeBlock } from '../../src/block'
-import { insert, prepend, remove } from '../../src/dom/node'
+import { Fragment, insert, normalizeBlock, prepend, remove } from '../src/block'
const node1 = document.createTextNode('node1')
const node2 = document.createTextNode('node2')
const node3 = document.createTextNode('node3')
const anchor = document.createTextNode('anchor')
-describe('element', () => {
+describe('node ops', () => {
test('normalizeBlock', () => {
expect(normalizeBlock([node1, node2, node3])).toEqual([node1, node2, node3])
expect(normalizeBlock([node1, [node2, [node3]]])).toEqual([
node2,
node3,
])
- expect(
- normalizeBlock([
- node1,
- { nodes: node2, anchor, [fragmentKey]: true },
- [node3],
- ]),
- ).toEqual([node1, node2, anchor, node3])
+ const frag = new Fragment(node2)
+ frag.anchor = anchor
+ expect(normalizeBlock([node1, frag, [node3]])).toEqual([
+ node1,
+ node2,
+ anchor,
+ node3,
+ ])
})
test('insert', () => {
test('prepend', () => {
const container = document.createElement('div')
prepend(container, [node1], node2)
- prepend(container, { nodes: node3, [fragmentKey]: true })
+ prepend(container, new Fragment(node3))
expect(Array.from(container.childNodes)).toEqual([node3, node1, node2])
})
test('remove', () => {
const container = document.createElement('div')
container.append(node1, node2, node3)
+ const frag = new Fragment(node3)
remove([node1], container)
- remove({ nodes: node3, [fragmentKey]: true }, container)
+ remove(frag, container)
expect(Array.from(container.childNodes)).toEqual([node2])
expect(() => remove(anchor, container)).toThrowError(
-import type { NodeRef } from 'packages/runtime-vapor/src/dom/templateRef'
+import type { NodeRef } from '../../src/dom/templateRef'
import {
createFor,
createIf,
+++ /dev/null
-import {
- type Component,
- type Directive,
- createVaporApp,
- resolveComponent,
- resolveDirective,
-} from 'packages/runtime-vapor/src/_old'
-import { makeRender } from '../_utils'
-
-const define = makeRender()
-
-describe('resolveAssets', () => {
- test('should work', () => {
- const FooBar = () => []
- const BarBaz = () => undefined
- let component1: Component | string
- let component2: Component | string
- let component3: Component | string
- let component4: Component | string
- let directive1: Directive
- let directive2: Directive
- let directive3: Directive
- let directive4: Directive
- const Root = define({
- render() {
- component1 = resolveComponent('FooBar')!
- directive1 = resolveDirective('BarBaz')!
- // camelize
- component2 = resolveComponent('Foo-bar')!
- directive2 = resolveDirective('Bar-baz')!
- // capitalize
- component3 = resolveComponent('fooBar')!
- directive3 = resolveDirective('barBaz')!
- // camelize and capitalize
- component4 = resolveComponent('foo-bar')!
- directive4 = resolveDirective('bar-baz')!
- return []
- },
- })
- const app = createVaporApp(Root.component)
- app.component('FooBar', FooBar)
- app.directive('BarBaz', BarBaz)
- const root = document.createElement('div')
- app.mount(root)
- expect(component1!).toBe(FooBar)
- expect(component2!).toBe(FooBar)
- expect(component3!).toBe(FooBar)
- expect(component4!).toBe(FooBar)
- expect(directive1!).toBe(BarBaz)
- expect(directive2!).toBe(BarBaz)
- expect(directive3!).toBe(BarBaz)
- expect(directive4!).toBe(BarBaz)
- })
-
- describe('warning', () => {
- test('used outside render() or setup()', () => {
- resolveComponent('foo')
- expect(
- '[Vue warn]: resolveComponent can only be used in render() or setup().',
- ).toHaveBeenWarned()
- resolveDirective('foo')
- expect(
- '[Vue warn]: resolveDirective can only be used in render() or setup().',
- ).toHaveBeenWarned()
- })
- test('not exist', () => {
- const Root = define({
- setup() {
- resolveComponent('foo')
- resolveDirective('bar')
- },
- })
- const app = createVaporApp(Root.component)
- const root = document.createElement('div')
- app.mount(root)
- expect('Failed to resolve component: foo').toHaveBeenWarned()
- expect('Failed to resolve directive: bar').toHaveBeenWarned()
- })
- })
-})
import { isArray } from '@vue/shared'
-import { type VaporComponentInstance, isVaporComponent } from './component'
-import { createComment, insert, remove } from './dom/node'
+import {
+ type VaporComponentInstance,
+ isVaporComponent,
+ mountComponent,
+ unmountComponent,
+} from './component'
+import { createComment } from './dom/node'
import { EffectScope } from '@vue/reactivity'
export type Block = Node | Fragment | VaporComponentInstance | Block[]
return nodes
}
-export function findFirstRootElement(
- instance: VaporComponentInstance,
-): Element | undefined {
- const element = getFirstNode(instance.block)
- return element instanceof Element ? element : undefined
+// TODO optimize
+export function isValidBlock(block: Block): boolean {
+ return (
+ normalizeBlock(block).filter(node => !(node instanceof Comment)).length > 0
+ )
}
-export function getFirstNode(block: Block | null): Node | undefined {
- if (!block || isVaporComponent(block)) return
- if (block instanceof Node) return block
- if (isArray(block)) {
- if (block.length === 1) {
- return getFirstNode(block[0])
+export function insert(
+ block: Block,
+ parent: ParentNode,
+ anchor: Node | null | 0 = null,
+): void {
+ if (block instanceof Node) {
+ parent.insertBefore(block, anchor === 0 ? parent.firstChild : anchor)
+ } else if (isVaporComponent(block)) {
+ mountComponent(block, parent, anchor)
+ } else if (isArray(block)) {
+ for (let i = 0; i < block.length; i++) {
+ insert(block[i], parent, anchor)
}
} else {
- return getFirstNode(block.nodes)
+ // fragment
+ insert(block.nodes, parent, anchor)
+ if (block.anchor) insert(block.anchor, parent, anchor)
}
}
-// TODO optimize
-export function isValidBlock(block: Block): boolean {
- return (
- normalizeBlock(block).filter(node => !(node instanceof Comment)).length > 0
- )
+export function prepend(parent: ParentNode, ...blocks: Block[]): void {
+ let i = blocks.length
+ while (i--) insert(blocks[i], parent, 0)
+}
+
+export function remove(block: Block, parent: ParentNode): void {
+ 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)
+ }
}
unregisterHMR,
warn,
} from '@vue/runtime-dom'
-import { type Block, isBlock } from './block'
+import { type Block, insert, isBlock, remove } from './block'
import { pauseTracking, proxyRefs, resetTracking } from '@vue/reactivity'
import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
import {
dynamicSlotsProxyHandlers,
getSlot,
} from './componentSlots'
-import { insert, remove } from './dom/node'
import { hmrReload, hmrRerender } from './hmr'
export { currentInstance } from '@vue/runtime-dom'
import { isArray } from '@vue/shared'
import { renderEffect } from '../renderEffect'
import { setText } from './prop'
-import type { Block } from '../block'
-import {
- isVaporComponent,
- mountComponent,
- unmountComponent,
-} from '../component'
-
-export function insert(
- block: Block,
- parent: ParentNode,
- anchor: Node | null | 0 = null,
-): void {
- if (block instanceof Node) {
- parent.insertBefore(block, anchor === 0 ? parent.firstChild : anchor)
- } else if (isVaporComponent(block)) {
- mountComponent(block, parent, anchor)
- } else if (isArray(block)) {
- for (let i = 0; i < block.length; i++) {
- insert(block[i], parent, anchor)
- }
- } else {
- // fragment
- insert(block.nodes, parent, anchor)
- if (block.anchor) insert(block.anchor, parent, anchor)
- }
-}
-
-export function prepend(parent: ParentNode, ...blocks: Block[]): void {
- for (const b of blocks) insert(b, parent, 0)
-}
-
-// TODO invoke unmount recursive
-export function remove(block: Block, parent: ParentNode): void {
- 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)
- }
-}
export function createTextNode(values?: any[] | (() => any[])): Text {
// eslint-disable-next-line no-restricted-globals
pushWarningContext,
simpleSetCurrentInstance,
} from '@vue/runtime-core'
-import { normalizeBlock } from './block'
+import { insert, normalizeBlock, remove } from './block'
import {
type VaporComponent,
type VaporComponentInstance,
mountComponent,
unmountComponent,
} from './component'
-import { insert, remove } from './dom/node'
export function hmrRerender(instance: VaporComponentInstance): void {
const normalized = normalizeBlock(instance.block)
export { defineVaporComponent } from './apiDefineComponent'
// compiler-use only
+export { insert, prepend, remove } from './block'
export { createComponent, createComponentWithFallback } from './component'
export { renderEffect } from './renderEffect'
export { createSlot } from './componentSlots'
export { template, children, next } from './dom/template'
-export { insert, prepend, remove, createTextNode } from './dom/node'
+export { createTextNode } from './dom/node'
export { setStyle } from './dom/style'
export {
setText,