]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: include children type in shapeFlag
authorEvan You <yyx990803@gmail.com>
Sun, 2 Jun 2019 11:40:50 +0000 (19:40 +0800)
committerEvan You <yyx990803@gmail.com>
Sun, 2 Jun 2019 11:40:50 +0000 (19:40 +0800)
packages/runtime-core/src/createRenderer.ts
packages/runtime-core/src/shapeFlags.ts
packages/runtime-core/src/vnode.ts

index 186dfb77a67b9fe32d0b51afa68586d05effc92b..7923465aefe96d530843613aab13428649ea0a1b 100644 (file)
@@ -14,7 +14,7 @@ import {
   createComponentInstance,
   setupStatefulComponent
 } from './component'
-import { isString, isArray, EMPTY_OBJ, EMPTY_ARR } from '@vue/shared'
+import { isString, EMPTY_OBJ, EMPTY_ARR } from '@vue/shared'
 import {
   TEXT,
   CLASS,
@@ -28,7 +28,13 @@ import { queueJob, queuePostFlushCb, flushPostFlushCbs } from './scheduler'
 import { effect, stop, ReactiveEffectOptions } from '@vue/observer'
 import { resolveProps } from './componentProps'
 import { resolveSlots } from './componentSlots'
-import { ELEMENT, STATEFUL_COMPONENT, FUNCTIONAL_COMPONENT } from './shapeFlags'
+import {
+  ELEMENT,
+  STATEFUL_COMPONENT,
+  FUNCTIONAL_COMPONENT,
+  TEXT_CHILDREN,
+  ARRAY_CHILDREN
+} from './shapeFlags'
 
 const prodEffectOptions = {
   scheduler: queueJob
@@ -193,15 +199,16 @@ export function createRenderer(options: RendererOptions) {
 
   function mountElement(vnode: VNode, container: HostNode, anchor?: HostNode) {
     const el = (vnode.el = hostCreateElement(vnode.type as string))
-    if (vnode.props != null) {
-      for (const key in vnode.props) {
-        hostPatchProp(el, key, vnode.props[key], null, false)
+    const { props, shapeFlag } = vnode
+    if (props != null) {
+      for (const key in props) {
+        hostPatchProp(el, key, props[key], null, false)
       }
     }
-    if (isString(vnode.children)) {
-      hostSetElementText(el, vnode.children)
-    } else if (isArray(vnode.children)) {
-      mountChildren(vnode.children, el)
+    if (shapeFlag & TEXT_CHILDREN) {
+      hostSetElementText(el, vnode.children as string)
+    } else if (shapeFlag & ARRAY_CHILDREN) {
+      mountChildren(vnode.children as VNodeChildren, el)
     }
     hostInsert(el, container, anchor)
   }
@@ -374,16 +381,16 @@ export function createRenderer(options: RendererOptions) {
     optimized?: boolean
   ) {
     const targetSelector = n2.props && n2.props.target
+    const { patchFlag, shapeFlag, children } = n2
     if (n1 == null) {
-      const children = n2.children
       const target = (n2.target = isString(targetSelector)
         ? hostQuerySelector(targetSelector)
         : null)
       if (target != null) {
-        if (isString(children)) {
-          hostSetElementText(target, children)
-        } else if (isArray(children)) {
-          mountChildren(children, target)
+        if (shapeFlag & TEXT_CHILDREN) {
+          hostSetElementText(target, children as string)
+        } else if (shapeFlag & ARRAY_CHILDREN) {
+          mountChildren(children as VNodeChildren, target)
         }
       } else {
         // TODO warn missing or invalid target
@@ -391,8 +398,8 @@ export function createRenderer(options: RendererOptions) {
     } else {
       // update content
       const target = (n2.target = n1.target)
-      if (n2.patchFlag === TEXT) {
-        hostSetElementText(target, n2.children as string)
+      if (patchFlag === TEXT) {
+        hostSetElementText(target, children as string)
       } else if (!optimized) {
         patchChildren(n1, n2, target)
       }
@@ -403,13 +410,12 @@ export function createRenderer(options: RendererOptions) {
           : null)
         if (nextTarget != null) {
           // move content
-          const children = n2.children
-          if (isString(children)) {
+          if (shapeFlag & TEXT_CHILDREN) {
             hostSetElementText(target, '')
-            hostSetElementText(nextTarget, children)
-          } else if (isArray(children)) {
-            for (let i = 0; i < children.length; i++) {
-              move(children[i] as VNode, nextTarget, null)
+            hostSetElementText(nextTarget, children as string)
+          } else if (shapeFlag & ARRAY_CHILDREN) {
+            for (let i = 0; i < (children as VNode[]).length; i++) {
+              move((children as VNode[])[i], nextTarget, null)
             }
           }
         } else {
@@ -516,10 +522,11 @@ export function createRenderer(options: RendererOptions) {
     optimized?: boolean
   ) {
     const c1 = n1 && n1.children
+    const prevShapeFlag = n1 ? n1.shapeFlag : 0
     const c2 = n2.children
 
     // fast path
-    const { patchFlag } = n2
+    const { patchFlag, shapeFlag } = n2
     if (patchFlag) {
       if (patchFlag & KEYED) {
         // this could be either fully-keyed or mixed (some keyed some not)
@@ -545,22 +552,28 @@ export function createRenderer(options: RendererOptions) {
       }
     }
 
-    if (isString(c2)) {
+    if (shapeFlag & TEXT_CHILDREN) {
       // text children fast path
-      if (isArray(c1)) {
+      if (prevShapeFlag & ARRAY_CHILDREN) {
         unmountChildren(c1 as VNode[])
       }
-      hostSetElementText(container, c2)
+      hostSetElementText(container, c2 as string)
     } else {
-      if (isString(c1)) {
+      if (prevShapeFlag & TEXT_CHILDREN) {
         hostSetElementText(container, '')
-        if (isArray(c2)) {
-          mountChildren(c2, container, anchor)
+        if (shapeFlag & ARRAY_CHILDREN) {
+          mountChildren(c2 as VNodeChildren, container, anchor)
         }
-      } else if (isArray(c1)) {
-        if (isArray(c2)) {
+      } else if (prevShapeFlag & ARRAY_CHILDREN) {
+        if (shapeFlag & ARRAY_CHILDREN) {
           // two arrays, cannot assume anything, do full diff
-          patchKeyedChildren(c1 as VNode[], c2, container, anchor, optimized)
+          patchKeyedChildren(
+            c1 as VNode[],
+            c2 as VNodeChildren,
+            container,
+            anchor,
+            optimized
+          )
         } else {
           // c2 is null in this case
           unmountChildren(c1 as VNode[], true)
@@ -791,7 +804,7 @@ export function createRenderer(options: RendererOptions) {
     const shouldRemoveChildren = vnode.type === Fragment && doRemove
     if (vnode.dynamicChildren != null) {
       unmountChildren(vnode.dynamicChildren, shouldRemoveChildren)
-    } else if (isArray(vnode.children)) {
+    } else if (vnode.shapeFlag & ARRAY_CHILDREN) {
       unmountChildren(vnode.children as VNode[], shouldRemoveChildren)
     }
     if (doRemove) {
index 4b75428b331b8dd034c98d0e32cc4ade94c6c60e..14a1931177e20b23a5d6703a3f56c8d834e8ab3a 100644 (file)
@@ -1,3 +1,6 @@
 export const ELEMENT = 1
 export const FUNCTIONAL_COMPONENT = 1 << 1
 export const STATEFUL_COMPONENT = 1 << 2
+export const TEXT_CHILDREN = 1 << 3
+export const ARRAY_CHILDREN = 1 << 4
+export const SLOTS_CHILDREN = 1 << 5
index c248a87a3c0b6dfc466eea7818c8d930ab1626ce..56951a259bdb205142e0026a4c47fe44d85f13f2 100644 (file)
@@ -3,7 +3,14 @@ import { ComponentInstance } from './component'
 import { HostNode } from './createRenderer'
 import { RawSlots } from './componentSlots'
 import { CLASS } from './patchFlags'
-import { ELEMENT, FUNCTIONAL_COMPONENT, STATEFUL_COMPONENT } from './shapeFlags'
+import {
+  ELEMENT,
+  FUNCTIONAL_COMPONENT,
+  STATEFUL_COMPONENT,
+  TEXT_CHILDREN,
+  ARRAY_CHILDREN,
+  SLOTS_CHILDREN
+} from './shapeFlags'
 
 export const Fragment = Symbol('Fragment')
 export const Text = Symbol('Text')
@@ -95,8 +102,10 @@ export function createVNode(
 ): VNode {
   // Allow passing 0 for props, this can save bytes on generated code.
   props = props || null
+  // normalize children
+  children = normalizeChildren(children) as NormalizedChildren
 
-  const shapeFlag = isString(type)
+  const typeFlag = isString(type)
     ? ELEMENT
     : isFunction(type)
       ? FUNCTIONAL_COMPONENT
@@ -104,16 +113,24 @@ export function createVNode(
         ? STATEFUL_COMPONENT
         : 0
 
+  const childFlag = isString(children)
+    ? TEXT_CHILDREN
+    : isArray(children)
+      ? ARRAY_CHILDREN
+      : isObject(children)
+        ? SLOTS_CHILDREN
+        : 0
+
   const vnode: VNode = {
     type,
     props,
     key: props && props.key,
-    children: normalizeChildren(children),
+    children,
     component: null,
     el: null,
     anchor: null,
     target: null,
-    shapeFlag,
+    shapeFlag: typeFlag | childFlag,
     patchFlag,
     dynamicProps,
     dynamicChildren: null
@@ -138,8 +155,8 @@ export function createVNode(
   if (
     shouldTrack &&
     (patchFlag ||
-      shapeFlag & STATEFUL_COMPONENT ||
-      shapeFlag & FUNCTIONAL_COMPONENT)
+      typeFlag & STATEFUL_COMPONENT ||
+      typeFlag & FUNCTIONAL_COMPONENT)
   ) {
     trackDynamicNode(vnode)
   }