mirror of https://github.com/vuejs/core.git
test(vapor): block tests
This commit is contained in:
parent
ec23ab9e3a
commit
b7aec139cb
|
@ -1,12 +1,11 @@
|
|||
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([
|
||||
|
@ -14,13 +13,14 @@ describe('element', () => {
|
|||
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', () => {
|
||||
|
@ -39,15 +39,16 @@ describe('element', () => {
|
|||
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(
|
|
@ -1,4 +1,4 @@
|
|||
import type { NodeRef } from 'packages/runtime-vapor/src/dom/templateRef'
|
||||
import type { NodeRef } from '../../src/dom/templateRef'
|
||||
import {
|
||||
createFor,
|
||||
createIf,
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
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()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,6 +1,11 @@
|
|||
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[]
|
||||
|
@ -84,28 +89,50 @@ export function normalizeBlock(block: Block): Node[] {
|
|||
return nodes
|
||||
}
|
||||
|
||||
export function findFirstRootElement(
|
||||
instance: VaporComponentInstance,
|
||||
): Element | undefined {
|
||||
const element = getFirstNode(instance.block)
|
||||
return element instanceof Element ? element : undefined
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
} else {
|
||||
return getFirstNode(block.nodes)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO optimize
|
||||
export function isValidBlock(block: Block): boolean {
|
||||
return (
|
||||
normalizeBlock(block).filter(node => !(node instanceof Comment)).length > 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 {
|
||||
// fragment
|
||||
insert(block.nodes, parent, anchor)
|
||||
if (block.anchor) insert(block.anchor, parent, anchor)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
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 {
|
||||
|
@ -41,7 +41,6 @@ import {
|
|||
dynamicSlotsProxyHandlers,
|
||||
getSlot,
|
||||
} from './componentSlots'
|
||||
import { insert, remove } from './dom/node'
|
||||
import { hmrReload, hmrRerender } from './hmr'
|
||||
|
||||
export { currentInstance } from '@vue/runtime-dom'
|
||||
|
|
|
@ -1,53 +1,6 @@
|
|||
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
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
pushWarningContext,
|
||||
simpleSetCurrentInstance,
|
||||
} from '@vue/runtime-core'
|
||||
import { normalizeBlock } from './block'
|
||||
import { insert, normalizeBlock, remove } from './block'
|
||||
import {
|
||||
type VaporComponent,
|
||||
type VaporComponentInstance,
|
||||
|
@ -13,7 +13,6 @@ import {
|
|||
mountComponent,
|
||||
unmountComponent,
|
||||
} from './component'
|
||||
import { insert, remove } from './dom/node'
|
||||
|
||||
export function hmrRerender(instance: VaporComponentInstance): void {
|
||||
const normalized = normalizeBlock(instance.block)
|
||||
|
|
|
@ -3,11 +3,12 @@ export { createVaporApp } from './apiCreateApp'
|
|||
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,
|
||||
|
|
Loading…
Reference in New Issue