]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: make portal tree-shakeable
authorEvan You <yyx990803@gmail.com>
Sat, 15 Feb 2020 16:40:09 +0000 (11:40 -0500)
committerEvan You <yyx990803@gmail.com>
Sat, 15 Feb 2020 22:44:37 +0000 (17:44 -0500)
14 files changed:
packages/runtime-core/__tests__/components/Portal.spec.ts [moved from packages/runtime-core/__tests__/rendererPortal.spec.ts with 97% similarity]
packages/runtime-core/__tests__/components/__snapshots__/Portal.spec.ts.snap [moved from packages/runtime-core/__tests__/__snapshots__/rendererPortal.spec.ts.snap with 100% similarity]
packages/runtime-core/src/apiCreateApp.ts
packages/runtime-core/src/components/KeepAlive.ts
packages/runtime-core/src/components/Portal.ts [new file with mode: 0644]
packages/runtime-core/src/components/Suspense.ts
packages/runtime-core/src/h.ts
packages/runtime-core/src/hydration.ts
packages/runtime-core/src/index.ts
packages/runtime-core/src/renderer.ts
packages/runtime-core/src/shapeFlags.ts [deleted file]
packages/runtime-core/src/vnode.ts
packages/server-renderer/src/renderToString.ts
packages/shared/src/shapeFlags.ts

similarity index 97%
rename from packages/runtime-core/__tests__/rendererPortal.spec.ts
rename to packages/runtime-core/__tests__/components/Portal.spec.ts
index c7d600bfca03ac293390ea54a4a06d461728600b..b71d5d6fba37bf86eec915524edc11b1cb335b1d 100644 (file)
@@ -12,7 +12,7 @@ import {
   TestElement,
   TestNode
 } from '@vue/runtime-test'
-import { VNodeArrayChildren } from '../src/vnode'
+import { VNodeArrayChildren } from '../../src/vnode'
 
 describe('renderer: portal', () => {
   test('should work', () => {
index d093b787c81e89a9d38dc2376ad815d7cf79ea75..e022d92f9557f0bc5cbe5fed2c3b39dbe71ea908 100644 (file)
@@ -141,19 +141,18 @@ export function createAppAPI<HostNode, HostElement>(
       },
 
       mixin(mixin: ComponentOptions) {
-        if (__DEV__ && !__FEATURE_OPTIONS__) {
-          warn('Mixins are only available in builds supporting Options API')
-        }
-
-        if (!context.mixins.includes(mixin)) {
-          context.mixins.push(mixin)
+        if (__FEATURE_OPTIONS__) {
+          if (!context.mixins.includes(mixin)) {
+            context.mixins.push(mixin)
+          } else if (__DEV__) {
+            warn(
+              'Mixin has already been applied to target app' +
+                (mixin.name ? `: ${mixin.name}` : '')
+            )
+          }
         } else if (__DEV__) {
-          warn(
-            'Mixin has already been applied to target app' +
-              (mixin.name ? `: ${mixin.name}` : '')
-          )
+          warn('Mixins are only available in builds supporting Options API')
         }
-
         return app
       },
 
index 4125131d2d7464313760d58b1ea13f28e9275c08..78bb824f97199df5f81b0eb8c3aa18316e1c0dba 100644 (file)
@@ -72,9 +72,9 @@ const KeepAliveImpl = {
     const sink = instance.sink as KeepAliveSink
     const {
       renderer: {
-        move,
-        unmount: _unmount,
-        options: { createElement }
+        m: move,
+        um: _unmount,
+        o: { createElement }
       },
       parentSuspense
     } = sink
diff --git a/packages/runtime-core/src/components/Portal.ts b/packages/runtime-core/src/components/Portal.ts
new file mode 100644 (file)
index 0000000..bbbaaad
--- /dev/null
@@ -0,0 +1,118 @@
+import { ComponentInternalInstance } from '../component'
+import { SuspenseBoundary } from './Suspense'
+import { RendererInternals, MoveType } from '../renderer'
+import { VNode, VNodeArrayChildren } from '../vnode'
+import { isString, ShapeFlags, PatchFlags } from '@vue/shared'
+import { warn } from '../warning'
+
+export const isPortal = (type: any): boolean => type.__isPortal
+
+export interface PortalProps {
+  target: string | object
+}
+
+export const PortalImpl = {
+  __isPortal: true,
+  process(
+    n1: VNode | null,
+    n2: VNode,
+    container: object,
+    anchor: object | null,
+    parentComponent: ComponentInternalInstance | null,
+    parentSuspense: SuspenseBoundary | null,
+    isSVG: boolean,
+    optimized: boolean,
+    {
+      mc: mountChildren,
+      pc: patchChildren,
+      pbc: patchBlockChildren,
+      m: move,
+      c: insertComment,
+      o: { querySelector, setElementText }
+    }: RendererInternals
+  ) {
+    const targetSelector = n2.props && n2.props.target
+    const { patchFlag, shapeFlag, children } = n2
+    if (n1 == null) {
+      if (__DEV__ && isString(targetSelector) && !querySelector) {
+        warn(
+          `Current renderer does not support string target for Portals. ` +
+            `(missing querySelector renderer option)`
+        )
+      }
+      const target = (n2.target = isString(targetSelector)
+        ? querySelector!(targetSelector)
+        : targetSelector)
+      if (target != null) {
+        if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
+          setElementText(target, children as string)
+        } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
+          mountChildren(
+            children as VNodeArrayChildren,
+            target,
+            null,
+            parentComponent,
+            parentSuspense,
+            isSVG,
+            optimized
+          )
+        }
+      } else if (__DEV__) {
+        warn('Invalid Portal target on mount:', target, `(${typeof target})`)
+      }
+    } else {
+      // update content
+      const target = (n2.target = n1.target)!
+      if (patchFlag === PatchFlags.TEXT) {
+        setElementText(target, children as string)
+      } else if (n2.dynamicChildren) {
+        // fast path when the portal happens to be a block root
+        patchBlockChildren(
+          n1.dynamicChildren!,
+          n2.dynamicChildren,
+          container,
+          parentComponent,
+          parentSuspense,
+          isSVG
+        )
+      } else if (!optimized) {
+        patchChildren(
+          n1,
+          n2,
+          target,
+          null,
+          parentComponent,
+          parentSuspense,
+          isSVG
+        )
+      }
+      // target changed
+      if (targetSelector !== (n1.props && n1.props.target)) {
+        const nextTarget = (n2.target = isString(targetSelector)
+          ? querySelector!(targetSelector)
+          : targetSelector)
+        if (nextTarget != null) {
+          // move content
+          if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
+            setElementText(target, '')
+            setElementText(nextTarget, children as string)
+          } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
+            for (let i = 0; i < (children as VNode[]).length; i++) {
+              move((children as VNode[])[i], nextTarget, null, MoveType.REORDER)
+            }
+          }
+        } else if (__DEV__) {
+          warn('Invalid Portal target on update:', target, `(${typeof target})`)
+        }
+      }
+    }
+    // insert an empty node as the placeholder for the portal
+    insertComment(n1, n2, container, anchor)
+  }
+}
+
+// Force-casted public typing for h and TSX props inference
+export const Portal = (PortalImpl as any) as {
+  __isPortal: true
+  new (): { $props: PortalProps }
+}
index c8f7d5abcb3d4e5c8bbcdce7f915bcd8c3c8a36e..56a4d5da383ecd58277ef4bc91711d67b555fdd5 100644 (file)
@@ -13,6 +13,8 @@ export interface SuspenseProps {
   onRecede?: () => void
 }
 
+export const isSuspense = (type: any): boolean => type.__isSuspense
+
 // Suspense exposes a component-like API, and is treated like a component
 // in the compiler, but internally it's a special built-in type that hooks
 // directly into the renderer.
@@ -79,8 +81,8 @@ function mountSuspense(
   rendererInternals: RendererInternals
 ) {
   const {
-    patch,
-    options: { createElement }
+    p: patch,
+    o: { createElement }
   } = rendererInternals
   const hiddenContainer = createElement('div')
   const suspense = (n2.suspense = createSuspenseBoundary(
@@ -138,7 +140,7 @@ function patchSuspense(
   parentComponent: ComponentInternalInstance | null,
   isSVG: boolean,
   optimized: boolean,
-  { patch }: RendererInternals
+  { p: patch }: RendererInternals
 ) {
   const suspense = (n2.suspense = n1.suspense)!
   suspense.vnode = n2
@@ -236,11 +238,11 @@ function createSuspenseBoundary<HostNode, HostElement>(
   rendererInternals: RendererInternals<HostNode, HostElement>
 ): SuspenseBoundary<HostNode, HostElement> {
   const {
-    patch,
-    move,
-    unmount,
-    next,
-    options: { parentNode }
+    p: patch,
+    m: move,
+    um: unmount,
+    n: next,
+    o: { parentNode }
   } = rendererInternals
 
   const suspense: SuspenseBoundary<HostNode, HostElement> = {
index fae16b8502f8d357399e6fc418e60e2b7078c971..30cb7a90fc5815a9070549e8fb799735c4c7fb0c 100644 (file)
@@ -4,9 +4,9 @@ import {
   createVNode,
   VNodeArrayChildren,
   Fragment,
-  Portal,
   isVNode
 } from './vnode'
+import { Portal, PortalProps } from './components/Portal'
 import { Suspense, SuspenseProps } from './components/Suspense'
 import { isObject, isArray } from '@vue/shared'
 import { RawSlots } from './componentSlots'
@@ -95,7 +95,7 @@ export function h(
 // portal (target prop is required)
 export function h(
   type: typeof Portal,
-  props: RawProps & { target: any },
+  props: RawProps & PortalProps,
   children: RawChildren
 ): VNode
 
index 2a9e0b1650225ffd8bd91ddb52738c78f0f8443e..8861a198401abe0b79e612c8311f7053705ca638 100644 (file)
@@ -1,12 +1,4 @@
-import {
-  VNode,
-  normalizeVNode,
-  Text,
-  Comment,
-  Static,
-  Fragment,
-  Portal
-} from './vnode'
+import { VNode, normalizeVNode, Text, Comment, Static, Fragment } from './vnode'
 import { queuePostFlushCb, flushPostFlushCbs } from './scheduler'
 import { ComponentInternalInstance } from './component'
 import { invokeDirectiveHook } from './directives'
@@ -18,7 +10,7 @@ import {
   isOn,
   isString
 } from '@vue/shared'
-import { RendererOptions, MountComponentFn } from './renderer'
+import { RendererInternals } from './renderer'
 
 export type RootHydrateFunction = (
   vnode: VNode<Node, Element>,
@@ -30,10 +22,10 @@ export type RootHydrateFunction = (
 // it out creates a ton of unnecessary complexity.
 // Hydration also depends on some renderer internal logic which needs to be
 // passed in via arguments.
-export function createHydrationFunctions(
-  mountComponent: MountComponentFn<Node, Element>,
-  patchProp: RendererOptions['patchProp']
-) {
+export function createHydrationFunctions({
+  mt: mountComponent,
+  o: { patchProp }
+}: RendererInternals<Node, Element>) {
   const hydrate: RootHydrateFunction = (vnode, container) => {
     if (__DEV__ && !container.hasChildNodes()) {
       warn(`Attempting to hydrate existing markup but container is empty.`)
@@ -65,9 +57,6 @@ export function createHydrationFunctions(
         // TODO handle potential hydration error if fragment didn't get
         // back anchor as expected.
         return anchor.nextSibling
-      case Portal:
-        hydratePortal(vnode, parentComponent)
-        return node.nextSibling
       default:
         if (shapeFlag & ShapeFlags.ELEMENT) {
           return hydrateElement(node as Element, vnode, parentComponent)
@@ -78,6 +67,9 @@ export function createHydrationFunctions(
           mountComponent(vnode, null, null, parentComponent, null, false)
           const subTree = vnode.component!.subTree
           return (subTree.anchor || subTree.el).nextSibling
+        } else if (shapeFlag & ShapeFlags.PORTAL) {
+          hydratePortal(vnode, parentComponent)
+          return node.nextSibling
         } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
           // TODO Suspense
         } else if (__DEV__) {
index f78c61a80f773c63e28e14246dd4e7aebaab6271..7a4be08e42385a8341270a9a577dda309a4d1eba 100644 (file)
@@ -49,7 +49,8 @@ export {
   createBlock
 } from './vnode'
 // Internal Components
-export { Text, Comment, Fragment, Portal } from './vnode'
+export { Text, Comment, Fragment } from './vnode'
+export { Portal, PortalProps } from './components/Portal'
 export { Suspense, SuspenseProps } from './components/Suspense'
 export { KeepAlive, KeepAliveProps } from './components/KeepAlive'
 export {
index dce719fa26062a34d10e2aa2714c9f9e7170f489..9d1c2a414a30f0e8968cdf12c42915e43193cdb0 100644 (file)
@@ -2,7 +2,6 @@ import {
   Text,
   Fragment,
   Comment,
-  Portal,
   cloneIfMounted,
   normalizeVNode,
   VNode,
@@ -59,9 +58,10 @@ import {
   queueEffectWithSuspense,
   SuspenseImpl
 } from './components/Suspense'
-import { ErrorCodes, callWithErrorHandling } from './errorHandling'
+import { PortalImpl } from './components/Portal'
 import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
 import { registerHMR, unregisterHMR } from './hmr'
+import { ErrorCodes, callWithErrorHandling } from './errorHandling'
 import { createHydrationFunctions, RootHydrateFunction } from './hydration'
 
 const __HMR__ = __BUNDLER__ && __DEV__
@@ -113,13 +113,19 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
 }
 
 // An object exposing the internals of a renderer, passed to tree-shakeable
-// features so that they can be decoupled from this file.
+// features so that they can be decoupled from this file. Keys are shortened
+// to optimize bundle size.
 export interface RendererInternals<HostNode = any, HostElement = any> {
-  patch: PatchFn<HostNode, HostElement>
-  unmount: UnmountFn<HostNode, HostElement>
-  move: MoveFn<HostNode, HostElement>
-  next: NextFn<HostNode, HostElement>
-  options: RendererOptions<HostNode, HostElement>
+  p: PatchFn<HostNode, HostElement>
+  um: UnmountFn<HostNode, HostElement>
+  m: MoveFn<HostNode, HostElement>
+  mt: MountComponentFn<HostNode, HostElement>
+  mc: MountChildrenFn<HostNode, HostElement>
+  pc: PatchChildrenFn<HostNode, HostElement>
+  pbc: PatchBlockChildrenFn<HostNode, HostElement>
+  n: NextFn<HostNode, HostElement>
+  o: RendererOptions<HostNode, HostElement>
+  c: ProcessTextOrCommentFn<HostNode, HostElement>
 }
 
 // These functions are created inside a closure and therefore there types cannot
@@ -136,11 +142,35 @@ type PatchFn<HostNode, HostElement> = (
   optimized?: boolean
 ) => void
 
-type UnmountFn<HostNode, HostElement> = (
-  vnode: VNode<HostNode, HostElement>,
+type MountChildrenFn<HostNode, HostElement> = (
+  children: VNodeArrayChildren<HostNode, HostElement>,
+  container: HostElement,
+  anchor: HostNode | null,
   parentComponent: ComponentInternalInstance | null,
   parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
-  doRemove?: boolean
+  isSVG: boolean,
+  optimized: boolean,
+  start?: number
+) => void
+
+type PatchChildrenFn<HostNode, HostElement> = (
+  n1: VNode<HostNode, HostElement> | null,
+  n2: VNode<HostNode, HostElement>,
+  container: HostElement,
+  anchor: HostNode | null,
+  parentComponent: ComponentInternalInstance | null,
+  parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
+  isSVG: boolean,
+  optimized?: boolean
+) => void
+
+type PatchBlockChildrenFn<HostNode, HostElement> = (
+  oldChildren: VNode<HostNode, HostElement>[],
+  newChildren: VNode<HostNode, HostElement>[],
+  fallbackContainer: HostElement,
+  parentComponent: ComponentInternalInstance | null,
+  parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
+  isSVG: boolean
 ) => void
 
 type MoveFn<HostNode, HostElement> = (
@@ -155,6 +185,13 @@ type NextFn<HostNode, HostElement> = (
   vnode: VNode<HostNode, HostElement>
 ) => HostNode | null
 
+type UnmountFn<HostNode, HostElement> = (
+  vnode: VNode<HostNode, HostElement>,
+  parentComponent: ComponentInternalInstance | null,
+  parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
+  doRemove?: boolean
+) => void
+
 type UnmountChildrenFn<HostNode, HostElement> = (
   children: VNode<HostNode, HostElement>[],
   parentComponent: ComponentInternalInstance | null,
@@ -172,6 +209,13 @@ export type MountComponentFn<HostNode, HostElement> = (
   isSVG: boolean
 ) => void
 
+type ProcessTextOrCommentFn<HostNode, HostElement> = (
+  n1: VNode<HostNode, HostElement> | null,
+  n2: VNode<HostNode, HostElement>,
+  container: HostElement,
+  anchor: HostNode | null
+) => void
+
 export type SetupRenderEffectFn<HostNode, HostElement> = (
   instance: ComponentInternalInstance,
   initialVNode: VNode<HostNode, HostElement>,
@@ -282,7 +326,6 @@ function baseCreateRenderer<
     setElementText: hostSetElementText,
     parentNode: hostParentNode,
     nextSibling: hostNextSibling,
-    querySelector: hostQuerySelector,
     setScopeId: hostSetScopeId = NOOP,
     cloneNode: hostCloneNode,
     insertStaticContent: hostInsertStaticContent
@@ -332,18 +375,6 @@ function baseCreateRenderer<
           optimized
         )
         break
-      case Portal:
-        processPortal(
-          n1,
-          n2,
-          container,
-          anchor,
-          parentComponent,
-          parentSuspense,
-          isSVG,
-          optimized
-        )
-        break
       default:
         if (shapeFlag & ShapeFlags.ELEMENT) {
           processElement(
@@ -367,6 +398,18 @@ function baseCreateRenderer<
             isSVG,
             optimized
           )
+        } else if (shapeFlag & ShapeFlags.PORTAL) {
+          ;(type as typeof PortalImpl).process(
+            n1,
+            n2,
+            container,
+            anchor,
+            parentComponent,
+            parentSuspense,
+            isSVG,
+            optimized,
+            internals
+          )
         } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
           ;(type as typeof SuspenseImpl).process(
             n1,
@@ -385,11 +428,11 @@ function baseCreateRenderer<
     }
   }
 
-  const processText = (
-    n1: HostVNode | null,
-    n2: HostVNode,
-    container: HostElement,
-    anchor: HostNode | null
+  const processText: ProcessTextOrCommentFn<HostNode, HostElement> = (
+    n1,
+    n2,
+    container,
+    anchor
   ) => {
     if (n1 == null) {
       hostInsert(
@@ -405,11 +448,11 @@ function baseCreateRenderer<
     }
   }
 
-  const processCommentNode = (
-    n1: HostVNode | null,
-    n2: HostVNode,
-    container: HostElement,
-    anchor: HostNode | null
+  const processCommentNode: ProcessTextOrCommentFn<HostNode, HostElement> = (
+    n1,
+    n2,
+    container,
+    anchor
   ) => {
     if (n1 == null) {
       hostInsert(
@@ -552,15 +595,15 @@ function baseCreateRenderer<
     }
   }
 
-  const mountChildren = (
-    children: HostVNodeChildren,
-    container: HostElement,
-    anchor: HostNode | null,
-    parentComponent: ComponentInternalInstance | null,
-    parentSuspense: HostSuspenseBoundary | null,
-    isSVG: boolean,
-    optimized: boolean,
-    start: number = 0
+  const mountChildren: MountChildrenFn<HostNode, HostElement> = (
+    children,
+    container,
+    anchor,
+    parentComponent,
+    parentSuspense,
+    isSVG,
+    optimized,
+    start = 0
   ) => {
     for (let i = start; i < children.length; i++) {
       const child = (children[i] = optimized
@@ -716,13 +759,13 @@ function baseCreateRenderer<
   }
 
   // The fast path for blocks.
-  const patchBlockChildren = (
-    oldChildren: HostVNode[],
-    newChildren: HostVNode[],
-    fallbackContainer: HostElement,
-    parentComponent: ComponentInternalInstance | null,
-    parentSuspense: HostSuspenseBoundary | null,
-    isSVG: boolean
+  const patchBlockChildren: PatchBlockChildrenFn<HostNode, HostElement> = (
+    oldChildren,
+    newChildren,
+    fallbackContainer,
+    parentComponent,
+    parentSuspense,
+    isSVG
   ) => {
     for (let i = 0; i < newChildren.length; i++) {
       const oldVNode = oldChildren[i]
@@ -883,100 +926,6 @@ function baseCreateRenderer<
     }
   }
 
-  const processPortal = (
-    n1: HostVNode | null,
-    n2: HostVNode,
-    container: HostElement,
-    anchor: HostNode | null,
-    parentComponent: ComponentInternalInstance | null,
-    parentSuspense: HostSuspenseBoundary | null,
-    isSVG: boolean,
-    optimized: boolean
-  ) => {
-    const targetSelector = n2.props && n2.props.target
-    const { patchFlag, shapeFlag, children } = n2
-    if (n1 == null) {
-      if (__DEV__ && isString(targetSelector) && !hostQuerySelector) {
-        warn(
-          `Current renderer does not support string target for Portals. ` +
-            `(missing querySelector renderer option)`
-        )
-      }
-      const target = (n2.target = isString(targetSelector)
-        ? hostQuerySelector!(targetSelector)
-        : targetSelector)
-      if (target != null) {
-        if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
-          hostSetElementText(target, children as string)
-        } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
-          mountChildren(
-            children as HostVNodeChildren,
-            target,
-            null,
-            parentComponent,
-            parentSuspense,
-            isSVG,
-            optimized
-          )
-        }
-      } else if (__DEV__) {
-        warn('Invalid Portal target on mount:', target, `(${typeof target})`)
-      }
-    } else {
-      // update content
-      const target = (n2.target = n1.target)!
-      if (patchFlag === PatchFlags.TEXT) {
-        hostSetElementText(target, children as string)
-      } else if (n2.dynamicChildren) {
-        // fast path when the portal happens to be a block root
-        patchBlockChildren(
-          n1.dynamicChildren!,
-          n2.dynamicChildren,
-          container,
-          parentComponent,
-          parentSuspense,
-          isSVG
-        )
-      } else if (!optimized) {
-        patchChildren(
-          n1,
-          n2,
-          target,
-          null,
-          parentComponent,
-          parentSuspense,
-          isSVG
-        )
-      }
-      // target changed
-      if (targetSelector !== (n1.props && n1.props.target)) {
-        const nextTarget = (n2.target = isString(targetSelector)
-          ? hostQuerySelector!(targetSelector)
-          : targetSelector)
-        if (nextTarget != null) {
-          // move content
-          if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
-            hostSetElementText(target, '')
-            hostSetElementText(nextTarget, children as string)
-          } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
-            for (let i = 0; i < (children as HostVNode[]).length; i++) {
-              move(
-                (children as HostVNode[])[i],
-                nextTarget,
-                null,
-                MoveType.REORDER
-              )
-            }
-          }
-        } else if (__DEV__) {
-          warn('Invalid Portal target on update:', target, `(${typeof target})`)
-        }
-      }
-    }
-    // insert an empty node as the placeholder for the portal
-    processCommentNode(n1, n2, container, anchor)
-  }
-
   const processComponent = (
     n1: HostVNode | null,
     n2: HostVNode,
@@ -1222,15 +1171,15 @@ function baseCreateRenderer<
     resolveSlots(instance, nextVNode.children)
   }
 
-  const patchChildren = (
-    n1: HostVNode | null,
-    n2: HostVNode,
-    container: HostElement,
-    anchor: HostNode | null,
-    parentComponent: ComponentInternalInstance | null,
-    parentSuspense: HostSuspenseBoundary | null,
-    isSVG: boolean,
-    optimized: boolean = false
+  const patchChildren: PatchChildrenFn<HostNode, HostElement> = (
+    n1,
+    n2,
+    container,
+    anchor,
+    parentComponent,
+    parentSuspense,
+    isSVG,
+    optimized = false
   ) => {
     const c1 = n1 && n1.children
     const prevShapeFlag = n1 ? n1.shapeFlag : 0
@@ -1899,20 +1848,25 @@ function baseCreateRenderer<
   }
 
   const internals: RendererInternals<HostNode, HostElement> = {
-    patch,
-    unmount,
-    move,
-    next: getNextHostNode,
-    options
+    p: patch,
+    um: unmount,
+    m: move,
+    mt: mountComponent,
+    mc: mountChildren,
+    pc: patchChildren,
+    pbc: patchBlockChildren,
+    n: getNextHostNode,
+    c: processCommentNode,
+    o: options
   }
 
   let hydrate: ReturnType<typeof createHydrationFunctions>[0] | undefined
   let hydrateNode: ReturnType<typeof createHydrationFunctions>[1] | undefined
   if (createHydrationFns) {
-    ;[hydrate, hydrateNode] = createHydrationFns(
-      mountComponent as MountComponentFn<Node, Element>,
-      hostPatchProp
-    )
+    ;[hydrate, hydrateNode] = createHydrationFns(internals as RendererInternals<
+      Node,
+      Element
+    >)
   }
 
   return {
diff --git a/packages/runtime-core/src/shapeFlags.ts b/packages/runtime-core/src/shapeFlags.ts
deleted file mode 100644 (file)
index c5d4f6f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-export const enum ShapeFlags {
-  ELEMENT = 1,
-  FUNCTIONAL_COMPONENT = 1 << 1,
-  STATEFUL_COMPONENT = 1 << 2,
-  TEXT_CHILDREN = 1 << 3,
-  ARRAY_CHILDREN = 1 << 4,
-  SLOTS_CHILDREN = 1 << 5,
-  SUSPENSE = 1 << 6,
-  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 7,
-  COMPONENT_KEPT_ALIVE = 1 << 8,
-  COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
-}
index 440eb270f181505f0cdf48fc3798ef4bf8fdf456..7b415ddbc67105a4b4b88a7c14eba4694cebda9f 100644 (file)
@@ -19,12 +19,16 @@ import {
 import { RawSlots } from './componentSlots'
 import { isReactive, Ref } from '@vue/reactivity'
 import { AppContext } from './apiCreateApp'
-import { SuspenseBoundary } from './components/Suspense'
+import {
+  SuspenseImpl,
+  isSuspense,
+  SuspenseBoundary
+} from './components/Suspense'
 import { DirectiveBinding } from './directives'
-import { SuspenseImpl } from './components/Suspense'
 import { TransitionHooks } from './components/BaseTransition'
 import { warn } from './warning'
 import { currentScopeId } from './helpers/scopeId'
+import { PortalImpl, isPortal } from './components/Portal'
 
 export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
   __isFragment: true
@@ -32,12 +36,6 @@ export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
     $props: VNodeProps
   }
 }
-export const Portal = (Symbol(__DEV__ ? 'Portal' : undefined) as any) as {
-  __isPortal: true
-  new (): {
-    $props: VNodeProps & { target: string | object }
-  }
-}
 export const Text = Symbol(__DEV__ ? 'Text' : undefined)
 export const Comment = Symbol(__DEV__ ? 'Comment' : undefined)
 export const Static = Symbol(__DEV__ ? 'Static' : undefined)
@@ -45,11 +43,11 @@ export const Static = Symbol(__DEV__ ? 'Static' : undefined)
 export type VNodeTypes =
   | string
   | Component
-  | typeof Fragment
-  | typeof Portal
   | typeof Text
   | typeof Static
   | typeof Comment
+  | typeof Fragment
+  | typeof PortalImpl
   | typeof SuspenseImpl
 
 export interface VNodeProps {
@@ -239,13 +237,15 @@ export function createVNode(
   // encode the vnode type information into a bitmap
   const shapeFlag = isString(type)
     ? ShapeFlags.ELEMENT
-    : __FEATURE_SUSPENSE__ && (type as any).__isSuspense === true
+    : __FEATURE_SUSPENSE__ && isSuspense(type)
       ? ShapeFlags.SUSPENSE
-      : isObject(type)
-        ? ShapeFlags.STATEFUL_COMPONENT
-        : isFunction(type)
-          ? ShapeFlags.FUNCTIONAL_COMPONENT
-          : 0
+      : isPortal(type)
+        ? ShapeFlags.PORTAL
+        : isObject(type)
+          ? ShapeFlags.STATEFUL_COMPONENT
+          : isFunction(type)
+            ? ShapeFlags.FUNCTIONAL_COMPONENT
+            : 0
 
   const vnode: VNode = {
     _isVNode: true,
index b7bd38d3135f139ff88094e975e213cee62412ab..3e6d8056bd34e397e4921dbc01d8135eb530f3ac 100644 (file)
@@ -8,7 +8,6 @@ import {
   Text,
   Comment,
   Fragment,
-  Portal,
   ssrUtils,
   Slots,
   warn,
@@ -251,14 +250,13 @@ function renderVNode(
       renderVNodeChildren(push, children as VNodeArrayChildren, parentComponent)
       push(`<!---->`)
       break
-    case Portal:
-      renderPortal(vnode, parentComponent)
-      break
     default:
       if (shapeFlag & ShapeFlags.ELEMENT) {
         renderElement(push, vnode, parentComponent)
       } else if (shapeFlag & ShapeFlags.COMPONENT) {
         push(renderComponentVNode(vnode, parentComponent))
+      } else if (shapeFlag & ShapeFlags.PORTAL) {
+        renderPortal(vnode, parentComponent)
       } else if (shapeFlag & ShapeFlags.SUSPENSE) {
         // TODO
       } else {
index c5d4f6f835e197c82fc980a78af1859043631a58..93c5f78234b4faa7a4572523dd553bfe593d9069 100644 (file)
@@ -5,8 +5,9 @@ export const enum ShapeFlags {
   TEXT_CHILDREN = 1 << 3,
   ARRAY_CHILDREN = 1 << 4,
   SLOTS_CHILDREN = 1 << 5,
-  SUSPENSE = 1 << 6,
-  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 7,
-  COMPONENT_KEPT_ALIVE = 1 << 8,
+  PORTAL = 1 << 6,
+  SUSPENSE = 1 << 7,
+  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
+  COMPONENT_KEPT_ALIVE = 1 << 9,
   COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
 }