]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
test(vapor): block tests
authorEvan You <evan@vuejs.org>
Mon, 9 Dec 2024 12:57:40 +0000 (20:57 +0800)
committerEvan You <evan@vuejs.org>
Mon, 9 Dec 2024 12:57:40 +0000 (20:57 +0800)
packages/runtime-vapor/__tests__/block.spec.ts [moved from packages/runtime-vapor/__tests__/dom/element.spec.ts with 75% similarity]
packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
packages/runtime-vapor/__tests__/helpers/resolveAssets.spec.ts [deleted file]
packages/runtime-vapor/src/block.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/dom/node.ts
packages/runtime-vapor/src/hmr.ts
packages/runtime-vapor/src/index.ts

similarity index 75%
rename from packages/runtime-vapor/__tests__/dom/element.spec.ts
rename to packages/runtime-vapor/__tests__/block.spec.ts
index b273131a518a81cad6bd9e480233943270b667bd..ddd4035f600ae4fc17f53b957681c1304d5eb88f 100644 (file)
@@ -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(
index a6f237558034e366cd3771593cdf67a818a4f998..143f46929f9ec3111312d43feec04d3170837d27 100644 (file)
@@ -1,4 +1,4 @@
-import type { NodeRef } from 'packages/runtime-vapor/src/dom/templateRef'
+import type { NodeRef } from '../../src/dom/templateRef'
 import {
   createFor,
   createIf,
diff --git a/packages/runtime-vapor/__tests__/helpers/resolveAssets.spec.ts b/packages/runtime-vapor/__tests__/helpers/resolveAssets.spec.ts
deleted file mode 100644 (file)
index 10b8c67..0000000
+++ /dev/null
@@ -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()
-    })
-  })
-})
index a4212714c69abe192d95d1d66553116c3f189269..01cc30ceb576d0cd0401aed7d2604a214d4b94b9 100644 (file)
@@ -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
+// 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)
+  }
 }
index a70bbdc9a20777b8ea65d1e00cca389fb5d1b2a2..688fe29f51aeae48031aba0fa51c46595585552d 100644 (file)
@@ -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'
index e54966d83932f6a819f5d42104ce609683821b74..5a50cd0aa11e3d47c75c23786e6f847139cddbae 100644 (file)
@@ -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
index f01b337bdeeef1d3dff4e7149e7a56dae9573ded..eb2d937735f629185c88e22a75f176975f513fb0 100644 (file)
@@ -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)
index ba47805b4821ecc8fdfa3c8b0fca3babee9d9574..6c22332af9de7852995a6d3983e1a7d412867d22 100644 (file)
@@ -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,