]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(provide): warn when using `provide` after mounting (#13954)
authorskirtle <65301168+skirtles-code@users.noreply.github.com>
Mon, 24 Nov 2025 06:54:12 +0000 (06:54 +0000)
committerGitHub <noreply@github.com>
Mon, 24 Nov 2025 06:54:12 +0000 (14:54 +0800)
close #13921
close #13924

packages/runtime-core/__tests__/apiInject.spec.ts
packages/runtime-core/src/apiInject.ts

index e5c9267e5bb1807a4028949084fad19f7d1662f4..27dc9677f1bda7748e7eaca2fa8593d62eadea76 100644 (file)
@@ -6,6 +6,7 @@ import {
   hasInjectionContext,
   inject,
   nextTick,
+  onMounted,
   provide,
   reactive,
   readonly,
@@ -372,4 +373,46 @@ describe('api: provide/inject', () => {
       })
     })
   })
+
+  describe('warnings for incorrect usage', () => {
+    it('should warn when inject() is called outside setup', () => {
+      inject('foo', 'bar')
+      expect(`inject() can only be used`).toHaveBeenWarned()
+    })
+
+    it('should warn when provide() is called outside setup', () => {
+      provide('foo', 'bar')
+      expect(`provide() can only be used`).toHaveBeenWarned()
+    })
+
+    it('should warn when provide() is called from a render function', () => {
+      const Provider = {
+        setup() {
+          return () => {
+            provide('foo', 'bar')
+          }
+        },
+      }
+
+      const root = nodeOps.createElement('div')
+      render(h(Provider), root)
+      expect(`provide() can only be used`).toHaveBeenWarned()
+    })
+
+    it('should warn when provide() is called from onMounted', () => {
+      const Provider = {
+        setup() {
+          onMounted(() => {
+            provide('foo', 'bar')
+          })
+
+          return () => null
+        },
+      }
+
+      const root = nodeOps.createElement('div')
+      render(h(Provider), root)
+      expect(`provide() can only be used`).toHaveBeenWarned()
+    })
+  })
 })
index d5c97a52b8360d7b1d5eefbc435a5a6863841db9..af59984fe00483e41adad7359e7ae3eaf0c3166b 100644 (file)
@@ -11,11 +11,12 @@ export function provide<T, K = InjectionKey<T> | string | number>(
   key: K,
   value: K extends InjectionKey<infer V> ? V : T,
 ): void {
-  if (!currentInstance) {
-    if (__DEV__) {
+  if (__DEV__) {
+    if (!currentInstance || currentInstance.isMounted) {
       warn(`provide() can only be used inside setup().`)
     }
-  } else {
+  }
+  if (currentInstance) {
     let provides = currentInstance.provides
     // by default an instance inherits its parent's provides object
     // but when it needs to provide values of its own, it creates its