Evan You пре 1 година
родитељ
комит
b7aec139cb

+ 13 - 12
packages/runtime-vapor/__tests__/dom/element.spec.ts → packages/runtime-vapor/__tests__/block.spec.ts

@@ -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 - 1
packages/runtime-vapor/__tests__/dom/templateRef.spec.ts

@@ -1,4 +1,4 @@
-import type { NodeRef } from 'packages/runtime-vapor/src/dom/templateRef'
+import type { NodeRef } from '../../src/dom/templateRef'
 import {
   createFor,
   createIf,

+ 0 - 80
packages/runtime-vapor/__tests__/helpers/resolveAssets.spec.ts

@@ -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()
-    })
-  })
-})

+ 46 - 19
packages/runtime-vapor/src/block.ts

@@ -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)
+  }
 }

+ 1 - 2
packages/runtime-vapor/src/component.ts

@@ -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'

+ 0 - 47
packages/runtime-vapor/src/dom/node.ts

@@ -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

+ 1 - 2
packages/runtime-vapor/src/hmr.ts

@@ -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)

+ 2 - 1
packages/runtime-vapor/src/index.ts

@@ -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,