]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): fix provide function data access in extends/mixins
authorEvan You <yyx990803@gmail.com>
Thu, 8 Oct 2020 01:47:01 +0000 (21:47 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 8 Oct 2020 01:47:01 +0000 (21:47 -0400)
fix #2300

packages/runtime-core/__tests__/apiOptions.spec.ts
packages/runtime-core/src/componentOptions.ts

index 6b6014c05cc7f6fb5cff273e63f5e867123e33f4..ad2c7106a8059d30c2b0a3d89a52ed830a23c604 100644 (file)
@@ -324,6 +324,36 @@ describe('api: options', () => {
     expect(renderToString(h(Root))).toBe(`11112345`)
   })
 
+  test('provide accessing data in extends', () => {
+    const Base = defineComponent({
+      data() {
+        return {
+          a: 1
+        }
+      },
+      provide() {
+        return {
+          a: this.a
+        }
+      }
+    })
+
+    const Child = {
+      inject: ['a'],
+      render() {
+        return (this as any).a
+      }
+    }
+
+    const Root = defineComponent({
+      extends: Base,
+      render() {
+        return h(Child)
+      }
+    })
+    expect(renderToString(h(Root))).toBe(`1`)
+  })
+
   test('lifecycle', async () => {
     const count = ref(0)
     const root = nodeOps.createElement('div')
index 57bd57e3d8573b3ee3e3f1b578a7518087f254ec..ee4062ba8b96a7cd8ccb5abd288e215deb5552cd 100644 (file)
@@ -430,6 +430,7 @@ export function applyOptions(
   options: ComponentOptions,
   deferredData: DataFn[] = [],
   deferredWatch: ComponentWatchOptions[] = [],
+  deferredProvide: (Data | Function)[] = [],
   asMixin: boolean = false
 ) {
   const {
@@ -483,16 +484,29 @@ export function applyOptions(
     )
     isInBeforeCreate = false
     // global mixins are applied first
-    applyMixins(instance, globalMixins, deferredData, deferredWatch)
+    applyMixins(
+      instance,
+      globalMixins,
+      deferredData,
+      deferredWatch,
+      deferredProvide
+    )
   }
 
   // extending a base component...
   if (extendsOptions) {
-    applyOptions(instance, extendsOptions, deferredData, deferredWatch, true)
+    applyOptions(
+      instance,
+      extendsOptions,
+      deferredData,
+      deferredWatch,
+      deferredProvide,
+      true
+    )
   }
   // local mixins
   if (mixins) {
-    applyMixins(instance, mixins, deferredData, deferredWatch)
+    applyMixins(instance, mixins, deferredData, deferredWatch, deferredProvide)
   }
 
   const checkDuplicateProperties = __DEV__ ? createDuplicateChecker() : null
@@ -634,12 +648,17 @@ export function applyOptions(
   }
 
   if (provideOptions) {
-    const provides = isFunction(provideOptions)
-      ? provideOptions.call(publicThis)
-      : provideOptions
-    for (const key in provides) {
-      provide(key, provides[key])
-    }
+    deferredProvide.push(provideOptions)
+  }
+  if (!asMixin && deferredProvide.length) {
+    deferredProvide.forEach(provideOptions => {
+      const provides = isFunction(provideOptions)
+        ? provideOptions.call(publicThis)
+        : provideOptions
+      for (const key in provides) {
+        provide(key, provides[key])
+      }
+    })
   }
 
   // asset options.
@@ -777,10 +796,18 @@ function applyMixins(
   instance: ComponentInternalInstance,
   mixins: ComponentOptions[],
   deferredData: DataFn[],
-  deferredWatch: ComponentWatchOptions[]
+  deferredWatch: ComponentWatchOptions[],
+  deferredProvide: (Data | Function)[]
 ) {
   for (let i = 0; i < mixins.length; i++) {
-    applyOptions(instance, mixins[i], deferredData, deferredWatch, true)
+    applyOptions(
+      instance,
+      mixins[i],
+      deferredData,
+      deferredWatch,
+      deferredProvide,
+      true
+    )
   }
 }