]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(runtime-core): remove need for internal instance sink
authorEvan You <yyx990803@gmail.com>
Thu, 16 Apr 2020 14:09:13 +0000 (10:09 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 16 Apr 2020 14:09:20 +0000 (10:09 -0400)
packages/runtime-core/__tests__/componentProxy.spec.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentProxy.ts
packages/runtime-core/src/components/KeepAlive.ts
packages/runtime-core/src/renderer.ts

index 753dbac4b413ef0a23114e1bfb976ab857899858..cd03ce7022483c8e47514354fc0a9a0df21ce563 100644 (file)
@@ -101,7 +101,7 @@ describe('component: proxy', () => {
     expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
   })
 
-  test('sink', async () => {
+  test('user attached properties', async () => {
     let instance: ComponentInternalInstance
     let instanceProxy: any
     const Comp = {
@@ -116,7 +116,7 @@ describe('component: proxy', () => {
     render(h(Comp), nodeOps.createElement('div'))
     instanceProxy.foo = 1
     expect(instanceProxy.foo).toBe(1)
-    expect(instance!.sink.foo).toBe(1)
+    expect(instance!.proxyTarget.foo).toBe(1)
   })
 
   test('globalProperties', () => {
@@ -140,8 +140,8 @@ describe('component: proxy', () => {
 
     // set should overwrite globalProperties with local
     instanceProxy.foo = 2
-    expect(instanceProxy.foo).toBe(2)
-    expect(instance!.sink.foo).toBe(2)
+    // expect(instanceProxy.foo).toBe(2)
+    expect(instance!.proxyTarget.foo).toBe(2)
     // should not affect global
     expect(app.config.globalProperties.foo).toBe(1)
   })
@@ -188,7 +188,7 @@ describe('component: proxy', () => {
     expect('$foobar' in instanceProxy).toBe(false)
     expect('baz' in instanceProxy).toBe(false)
 
-    // set non-existent (goes into sink)
+    // set non-existent (goes into proxyTarget sink)
     instanceProxy.baz = 1
     expect('baz' in instanceProxy).toBe(true)
 
index 9bbcc85677f3932461128ada1b43d023cbec2b35..da31dfdaaacaf08debfbc07550e56b572130a686 100644 (file)
@@ -143,6 +143,11 @@ export interface ComponentInternalInstance {
   attrs: Data
   slots: InternalSlots
   proxy: ComponentPublicInstance | null
+  // The target object for the public instance proxy. In dev mode, we also
+  // define getters for all known instance properties on it so it can be
+  // properly inspected in the console. These getters are skipped in prod mode
+  // for performance. In addition, any user attached properties
+  // (via `this.x = ...`) are also stored on this object.
   proxyTarget: ComponentPublicProxyTarget
   // alternative proxy used only for runtime-compiled render functions using
   // `with` block
@@ -156,9 +161,6 @@ export interface ComponentInternalInstance {
   asyncDep: Promise<any> | null
   asyncResolved: boolean
 
-  // storage for any extra properties
-  sink: { [key: string]: any }
-
   // lifecycle
   isMounted: boolean
   isUnmounted: boolean
@@ -230,10 +232,6 @@ export function createComponentInstance(
     asyncDep: null,
     asyncResolved: false,
 
-    // user namespace for storing whatever the user assigns to `this`
-    // can also be used as a wildcard storage for ad-hoc injections internally
-    sink: {},
-
     // lifecycle hooks
     // not using enums here because it results in computed properties
     isMounted: false,
index 74c5c5912459f8199050e1c7ac3f0f7257795e07..13954b40bad955189830628de206435542d6fe72 100644 (file)
@@ -95,7 +95,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
       props,
       accessCache,
       type,
-      sink,
+      proxyTarget,
       appContext
     } = instance
 
@@ -136,7 +136,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
       }
     }
 
-    // public $xxx properties & user-attached properties (sink)
+    // public $xxx properties &
+    // user-attached properties (falls through to proxyTarget)
     const publicGetter = publicPropertiesMap[key]
     let cssModule, globalProperties
     if (publicGetter) {
@@ -144,8 +145,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
         markAttrsAccessed()
       }
       return publicGetter(instance)
-    } else if (hasOwn(sink, key)) {
-      return sink[key]
+    } else if (hasOwn(proxyTarget, key)) {
+      return proxyTarget[key]
     } else if (
       (cssModule = type.__cssModules) &&
       (cssModule = cssModule[key])
@@ -190,8 +191,13 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
         )
       return false
     } else {
-      instance.sink[key] = value
-      if (__DEV__) {
+      if (__DEV__ && key in instance.appContext.config.globalProperties) {
+        Object.defineProperty(instance.proxyTarget, key, {
+          configurable: true,
+          enumerable: true,
+          value
+        })
+      } else {
         instance.proxyTarget[key] = value
       }
     }
@@ -200,7 +206,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
 
   has(
     {
-      _: { data, accessCache, renderContext, type, sink, appContext }
+      _: { data, accessCache, renderContext, type, proxyTarget, appContext }
     }: ComponentPublicProxyTarget,
     key: string
   ) {
@@ -210,7 +216,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
       hasOwn(renderContext, key) ||
       (type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
       hasOwn(publicPropertiesMap, key) ||
-      hasOwn(sink, key) ||
+      hasOwn(proxyTarget, key) ||
       hasOwn(appContext.config.globalProperties, key)
     )
   }
index ff53876c3165cd5048903c805c286f58f9c12952..50a4f7567c98542396f1c5d49635b6134d465c47 100644 (file)
@@ -18,7 +18,6 @@ import {
   invokeArrayFns
 } from '@vue/shared'
 import { watch } from '../apiWatch'
-import { SuspenseBoundary } from './Suspense'
 import {
   RendererInternals,
   queuePostRenderEffect,
@@ -27,6 +26,7 @@ import {
   RendererNode
 } from '../renderer'
 import { setTransitionHooks } from './BaseTransition'
+import { ComponentPublicProxyTarget } from '../componentProxy'
 
 type MatchPattern = string | RegExp | string[] | RegExp[]
 
@@ -40,9 +40,8 @@ type CacheKey = string | number | Component
 type Cache = Map<CacheKey, VNode>
 type Keys = Set<CacheKey>
 
-export interface KeepAliveSink {
+export interface KeepAliveContext extends ComponentPublicProxyTarget {
   renderer: RendererInternals
-  parentSuspense: SuspenseBoundary | null
   activate: (
     vnode: VNode,
     container: RendererElement,
@@ -76,25 +75,25 @@ const KeepAliveImpl = {
     let current: VNode | null = null
 
     const instance = getCurrentInstance()!
+    const parentSuspense = instance.suspense
 
-    // KeepAlive communicates with the instantiated renderer via the "sink"
-    // where the renderer passes in platform-specific functions, and the
-    // KeepAlive instance exposes activate/deactivate implementations.
+    // KeepAlive communicates with the instantiated renderer via the proxyTarget
+    // as a shared context where the renderer passes in its internals,
+    // and the KeepAlive instance exposes activate/deactivate implementations.
     // The whole point of this is to avoid importing KeepAlive directly in the
     // renderer to facilitate tree-shaking.
-    const sink = instance.sink as KeepAliveSink
+    const sharedContext = instance.proxyTarget as KeepAliveContext
     const {
       renderer: {
         p: patch,
         m: move,
         um: _unmount,
         o: { createElement }
-      },
-      parentSuspense
-    } = sink
+      }
+    } = sharedContext
     const storageContainer = createElement('div')
 
-    sink.activate = (vnode, container, anchor, isSVG, optimized) => {
+    sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
       const child = vnode.component!
       move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
       // in case props have changed
@@ -116,7 +115,7 @@ const KeepAliveImpl = {
       }, parentSuspense)
     }
 
-    sink.deactivate = (vnode: VNode) => {
+    sharedContext.deactivate = (vnode: VNode) => {
       move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
       queuePostRenderEffect(() => {
         const component = vnode.component!
index ab854b11f00af7e014e5d182ef863494e8e6b36e..39fbb3f11dbb2f1a48c332b93f3ebd596a1f049d 100644 (file)
@@ -53,7 +53,7 @@ import {
   SuspenseImpl
 } from './components/Suspense'
 import { TeleportImpl } from './components/Teleport'
-import { KeepAliveSink, isKeepAlive } from './components/KeepAlive'
+import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
 import { registerHMR, unregisterHMR } from './hmr'
 import {
   ErrorCodes,
@@ -949,7 +949,7 @@ function baseCreateRenderer(
   ) => {
     if (n1 == null) {
       if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
-        ;(parentComponent!.sink as KeepAliveSink).activate(
+        ;(parentComponent!.proxyTarget as KeepAliveContext).activate(
           n2,
           container,
           anchor,
@@ -998,9 +998,7 @@ function baseCreateRenderer(
 
     // inject renderer internals for keepAlive
     if (isKeepAlive(initialVNode)) {
-      const sink = instance.sink as KeepAliveSink
-      sink.renderer = internals
-      sink.parentSuspense = parentSuspense
+      ;(instance.proxyTarget as KeepAliveContext).renderer = internals
     }
 
     // resolve props and slots for setup context
@@ -1721,7 +1719,7 @@ function baseCreateRenderer(
 
     if (shapeFlag & ShapeFlags.COMPONENT) {
       if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
-        ;(parentComponent!.sink as KeepAliveSink).deactivate(vnode)
+        ;(parentComponent!.proxyTarget as KeepAliveContext).deactivate(vnode)
       } else {
         unmountComponent(vnode.component!, parentSuspense, doRemove)
       }