]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: separate setupState
authorEvan You <yyx990803@gmail.com>
Thu, 16 Apr 2020 15:50:33 +0000 (11:50 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 16 Apr 2020 15:50:33 +0000 (11:50 -0400)
packages/runtime-core/__tests__/componentProxy.spec.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentProxy.ts
packages/runtime-core/src/renderer.ts

index cd03ce7022483c8e47514354fc0a9a0df21ce563..8b88ca9b073ad78e605732da2bd3e161afb638c0 100644 (file)
@@ -35,7 +35,7 @@ describe('component: proxy', () => {
     expect(instance!.data.foo).toBe(2)
   })
 
-  test('renderContext', () => {
+  test('setupState', () => {
     let instance: ComponentInternalInstance
     let instanceProxy: any
     const Comp = {
@@ -55,7 +55,7 @@ describe('component: proxy', () => {
     render(h(Comp), nodeOps.createElement('div'))
     expect(instanceProxy.foo).toBe(1)
     instanceProxy.foo = 2
-    expect(instance!.renderContext.foo).toBe(2)
+    expect(instance!.setupState.foo).toBe(2)
   })
 
   test('should not expose non-declared props', () => {
index da31dfdaaacaf08debfbc07550e56b572130a686..53ee3e4186b0bf1c6fcfd0538fb8f9372abcfae3 100644 (file)
@@ -13,7 +13,7 @@ import {
   RuntimeCompiledPublicInstanceProxyHandlers,
   createDevProxyTarget,
   exposePropsOnDevProxyTarget,
-  exposeRenderContextOnDevProxyTarget
+  exposeSetupStateOnDevProxyTarget
 } from './componentProxy'
 import { ComponentPropsOptions, initProps } from './componentProps'
 import { Slots, initSlots, InternalSlots } from './componentSlots'
@@ -143,6 +143,13 @@ export interface ComponentInternalInstance {
   attrs: Data
   slots: InternalSlots
   proxy: ComponentPublicInstance | null
+  refs: Data
+  emit: EmitFn
+
+  // setup
+  setupState: Data
+  setupContext: SetupContext | 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
@@ -152,9 +159,6 @@ export interface ComponentInternalInstance {
   // alternative proxy used only for runtime-compiled render functions using
   // `with` block
   withProxy: ComponentPublicInstance | null
-  setupContext: SetupContext | null
-  refs: Data
-  emit: EmitFn
 
   // suspense related
   suspense: SuspenseBoundary | null
@@ -209,19 +213,20 @@ export function createComponentInstance(
     proxy: null,
     proxyTarget: null!, // to be immediately set
     withProxy: null,
-    setupContext: null,
     effects: null,
     provides: parent ? parent.provides : Object.create(appContext.provides),
     accessCache: null!,
     renderCache: [],
 
-    // setup context properties
+    // state
     renderContext: EMPTY_OBJ,
     data: EMPTY_OBJ,
     props: EMPTY_OBJ,
     attrs: EMPTY_OBJ,
     slots: EMPTY_OBJ,
     refs: EMPTY_OBJ,
+    setupState: EMPTY_OBJ,
+    setupContext: null,
 
     // per-instance asset storage (mutable during options resolution)
     components: Object.create(appContext.components),
@@ -392,9 +397,9 @@ export function handleSetupResult(
     }
     // setup returned bindings.
     // assuming a render function compiled from template is present.
-    instance.renderContext = reactive(setupResult)
+    instance.setupState = reactive(setupResult)
     if (__DEV__) {
-      exposeRenderContextOnDevProxyTarget(instance)
+      exposeSetupStateOnDevProxyTarget(instance)
     }
   } else if (__DEV__ && setupResult !== undefined) {
     warn(
index 13954b40bad955189830628de206435542d6fe72..d8f97c4b3d00e54697fe3a3db90545275736a181 100644 (file)
@@ -76,9 +76,10 @@ const publicPropertiesMap: Record<
 }
 
 const enum AccessTypes {
+  SETUP,
   DATA,
-  CONTEXT,
   PROPS,
+  CONTEXT,
   OTHER
 }
 
@@ -91,6 +92,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
   get({ _: instance }: ComponentPublicProxyTarget, key: string) {
     const {
       renderContext,
+      setupState,
       data,
       props,
       accessCache,
@@ -109,6 +111,8 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
       const n = accessCache![key]
       if (n !== undefined) {
         switch (n) {
+          case AccessTypes.SETUP:
+            return setupState[key]
           case AccessTypes.DATA:
             return data[key]
           case AccessTypes.CONTEXT:
@@ -117,22 +121,25 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
             return props![key]
           // default: just fallthrough
         }
+      } else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
+        accessCache![key] = AccessTypes.SETUP
+        return setupState[key]
       } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
         accessCache![key] = AccessTypes.DATA
         return data[key]
+      } else if (
+        // only cache other properties when instance has declared (thus stable)
+        // props
+        type.props &&
+        hasOwn(normalizePropsOptions(type.props)[0]!, key)
+      ) {
+        accessCache![key] = AccessTypes.PROPS
+        return props![key]
       } else if (renderContext !== EMPTY_OBJ && hasOwn(renderContext, key)) {
         accessCache![key] = AccessTypes.CONTEXT
         return renderContext[key]
-      } else if (type.props) {
-        // only cache other properties when instance has declared (thus stable)
-        // props
-        if (hasOwn(normalizePropsOptions(type.props)[0]!, key)) {
-          accessCache![key] = AccessTypes.PROPS
-          // return the value from propsProxy for ref unwrapping and readonly
-          return props![key]
-        } else {
-          accessCache![key] = AccessTypes.OTHER
-        }
+      } else {
+        accessCache![key] = AccessTypes.OTHER
       }
     }
 
@@ -170,23 +177,25 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
     key: string,
     value: any
   ): boolean {
-    const { data, renderContext } = instance
-    if (data !== EMPTY_OBJ && hasOwn(data, key)) {
+    const { data, setupState, renderContext } = instance
+    if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
+      setupState[key] = value
+    } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
       data[key] = value
-    } else if (hasOwn(renderContext, key)) {
-      renderContext[key] = value
-    } else if (key[0] === '$' && key.slice(1) in instance) {
+    } else if (key in instance.props) {
       __DEV__ &&
         warn(
-          `Attempting to mutate public property "${key}". ` +
-            `Properties starting with $ are reserved and readonly.`,
+          `Attempting to mutate prop "${key}". Props are readonly.`,
           instance
         )
       return false
-    } else if (key in instance.props) {
+    } else if (hasOwn(renderContext, key)) {
+      renderContext[key] = value
+    } else if (key[0] === '$' && key.slice(1) in instance) {
       __DEV__ &&
         warn(
-          `Attempting to mutate prop "${key}". Props are readonly.`,
+          `Attempting to mutate public property "${key}". ` +
+            `Properties starting with $ are reserved and readonly.`,
           instance
         )
       return false
@@ -206,15 +215,24 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
 
   has(
     {
-      _: { data, accessCache, renderContext, type, proxyTarget, appContext }
+      _: {
+        data,
+        setupState,
+        accessCache,
+        renderContext,
+        type,
+        proxyTarget,
+        appContext
+      }
     }: ComponentPublicProxyTarget,
     key: string
   ) {
     return (
       accessCache![key] !== undefined ||
       (data !== EMPTY_OBJ && hasOwn(data, key)) ||
-      hasOwn(renderContext, key) ||
+      (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||
       (type.props && hasOwn(normalizePropsOptions(type.props)[0]!, key)) ||
+      hasOwn(renderContext, key) ||
       hasOwn(publicPropertiesMap, key) ||
       hasOwn(proxyTarget, key) ||
       hasOwn(appContext.config.globalProperties, key)
@@ -306,15 +324,15 @@ export function exposePropsOnDevProxyTarget(
   }
 }
 
-export function exposeRenderContextOnDevProxyTarget(
+export function exposeSetupStateOnDevProxyTarget(
   instance: ComponentInternalInstance
 ) {
-  const { proxyTarget, renderContext } = instance
-  Object.keys(toRaw(renderContext)).forEach(key => {
+  const { proxyTarget, setupState } = instance
+  Object.keys(toRaw(setupState)).forEach(key => {
     Object.defineProperty(proxyTarget, key, {
       enumerable: true,
       configurable: true,
-      get: () => renderContext[key],
+      get: () => setupState[key],
       set: NOOP
     })
   })
index 39fbb3f11dbb2f1a48c332b93f3ebd596a1f049d..ad7551005945738cec7fdee3939457f328cbe571 100644 (file)
@@ -1899,14 +1899,14 @@ function baseCreateRenderer(
     }
     const oldRef = oldRawRef && oldRawRef[1]
     const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs
-    const renderContext = owner.renderContext
+    const setupState = owner.setupState
 
     // unset old ref
     if (oldRef != null && oldRef !== ref) {
       if (isString(oldRef)) {
         refs[oldRef] = null
-        if (hasOwn(renderContext, oldRef)) {
-          renderContext[oldRef] = null
+        if (hasOwn(setupState, oldRef)) {
+          setupState[oldRef] = null
         }
       } else if (isRef(oldRef)) {
         oldRef.value = null
@@ -1915,8 +1915,8 @@ function baseCreateRenderer(
 
     if (isString(ref)) {
       refs[ref] = value
-      if (hasOwn(renderContext, ref)) {
-        renderContext[ref] = value
+      if (hasOwn(setupState, ref)) {
+        setupState[ref] = value
       }
     } else if (isRef(ref)) {
       ref.value = value