]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix: resolveDynamicComponent should use context instance
authorEvan You <yyx990803@gmail.com>
Mon, 25 Nov 2019 15:04:40 +0000 (10:04 -0500)
committerEvan You <yyx990803@gmail.com>
Mon, 25 Nov 2019 16:41:28 +0000 (11:41 -0500)
packages/compiler-core/__tests__/transforms/transformElement.spec.ts
packages/compiler-core/src/transforms/transformElement.ts
packages/runtime-core/src/componentProxy.ts
packages/runtime-core/src/helpers/resolveAssets.ts

index 00f5274aba489be4b111762c766b468ea6a3767a..078ea9bc255b70c33cd6be12cd7857b1dd1b5d9f 100644 (file)
@@ -788,7 +788,8 @@ describe('compiler: element transform', () => {
             {
               type: NodeTypes.SIMPLE_EXPRESSION,
               content: 'foo'
-            }
+            },
+            '$'
           ]
         }
       ])
index e70588bbe2e9b3fbeb8f66e8e705a81568bc8720..e440bb66bfde9723b4b2da447a091ae9c768c3de 100644 (file)
@@ -86,7 +86,8 @@ export const transformElement: NodeTransform = (node, context) => {
         else if (isProp.exp) {
           dynamicComponent = createCallExpression(
             context.helper(RESOLVE_DYNAMIC_COMPONENT),
-            [isProp.exp]
+            // _ctx.$ exposes the owner instance of current render function
+            [isProp.exp, context.prefixIdentifiers ? `_ctx.$` : `$`]
           )
         }
       }
index ce3e36c9355f6f9a816f6ffb81fa95afd35c09e9..53f5aeba47084795d6381a967e58380ec573f285 100644 (file)
@@ -106,6 +106,9 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
       }
       // return the value from propsProxy for ref unwrapping and readonly
       return propsProxy![key]
+    } else if (key === '$') {
+      // reserved backdoor to access the internal instance
+      return target
     } else if (key === '$cache') {
       return target.renderCache || (target.renderCache = [])
     } else if (key === '$el') {
index 91283f0f60e5b3532e2f716db7fe34cb30ec89f4..423cd20b801bf67f60a03219642edf6bfcf2c622 100644 (file)
@@ -1,5 +1,9 @@
 import { currentRenderingInstance } from '../componentRenderUtils'
-import { currentInstance, Component } from '../component'
+import {
+  currentInstance,
+  Component,
+  ComponentInternalInstance
+} from '../component'
 import { Directive } from '../directives'
 import {
   camelize,
@@ -15,11 +19,16 @@ export function resolveComponent(name: string): Component | undefined {
 }
 
 export function resolveDynamicComponent(
-  component: unknown
+  component: unknown,
+  // Dynamic component resolution has to be called inline due to potential
+  // access to scope variables. When called inside slots it will be inside
+  // a different component's render cycle, so the owner instance must be passed
+  // in explicitly.
+  instance: ComponentInternalInstance
 ): Component | undefined {
   if (!component) return
   if (isString(component)) {
-    return resolveAsset('components', component)
+    return resolveAsset('components', component, instance)
   } else if (isFunction(component) || isObject(component)) {
     return component
   }
@@ -30,12 +39,24 @@ export function resolveDirective(name: string): Directive | undefined {
 }
 
 // overload 1: components
-function resolveAsset(type: 'components', name: string): Component | undefined
+function resolveAsset(
+  type: 'components',
+  name: string,
+  instance?: ComponentInternalInstance
+): Component | undefined
 // overload 2: directives
-function resolveAsset(type: 'directives', name: string): Directive | undefined
+function resolveAsset(
+  type: 'directives',
+  name: string,
+  instance?: ComponentInternalInstance
+): Directive | undefined
 
-function resolveAsset(type: 'components' | 'directives', name: string) {
-  const instance = currentRenderingInstance || currentInstance
+function resolveAsset(
+  type: 'components' | 'directives',
+  name: string,
+  instance: ComponentInternalInstance | null = currentRenderingInstance ||
+    currentInstance
+) {
   if (instance) {
     let camelized
     const registry = instance[type]