Skip to content

Conversation

skirtles-code
Copy link
Contributor

@skirtles-code skirtles-code commented Sep 30, 2025

Closes #13921.

Background

As far as I'm aware, provide is only intended to be used during the creation of a component. The provided values are expected to be locked in once the component renders. Any descendants shouldn't need to worry about timing, any provided values will be ready immediately and won't change. This is baked into the design of provide/inject.

I believe the original intention was for provide to only work directly inside setup (both the warning message and the documentation suggest this too). But, in practice, it doesn't check for that, it only checks for the availability of currentInstance. That is available in other places, such as inside lifecycle hooks.

As pointed out in #13921, calling provide inside a lifecycle hook does mostly work, but not completely. Some parts of the code appear to have been written under the assumption that the provided values are only set prior to mounting. In my opinion, this is a valid assumption and the only change that is required is to tighten up the warnings to avoid incorrect usage.

I've extended the warning to also check for currentInstance.isMounted. This will lead to a warning in cases like this:

onMounted(() => {
  provide('foo', 'bar')
})

Why isMounted?

I chose to use currentInstance.isMounted for my check because I think it reflects the underlying restriction. You could, for example, still use provide inside onBeforeMounted. I'm not sure why that would be useful, but so long as the component hasn't mounted yet I didn't see any reason to log a warning.

Impact on existing applications

This PR only adds extra warnings, it shouldn't change how provide behaves. If someone is using provide inside onMounted then it will still 'work' as it did previously, just with an extra warning. In that sense, it's relatively safe to merge and shouldn't impact production builds.

I've marked this change as a fix because I think it needs to be included in the changelog. There will likely be some people who encounter this warning after upgrading and it would be helpful for them to be able to find this PR.

I'm not sure what the use case for calling provide inside a lifecycle hook would be. It would still need to be called during the synchronous execution of the hook, so it isn't really suited to asynchronous tasks such as loading data. Perhaps there's a use case involving providing values that come from template refs?

In any case, if provide is being used inside onMounted then I believe the 'correct' way to handle that would be to provide a ref during setup instead, then update that ref from inside onMounted.

I'm not sure whether this would impact any libraries. I did have a quick look through VueUse. From what I could tell it doesn't use provide and inject much, so it shouldn't be a problem.

Tests

The existing warning message wasn't being tested. Most of the test cases I've added are testing the existing code on main, so even if the other changes in this PR aren't viable it may still be possible to merge some of those tests. Only the final test is actually testing my change to provide.

Summary by CodeRabbit

  • Bug Fixes

    • Improved development-time warnings for incorrect use of dependency injection APIs, including usage outside setup and after component mount.
    • Ensures warnings trigger reliably without affecting normal runtime behavior.
  • Tests

    • Added comprehensive test coverage for warning scenarios, including misuse in render functions and lifecycle hooks.

Copy link

coderabbitai bot commented Sep 30, 2025

Walkthrough

Adds warning tests for misuse of provide/inject and updates provide() runtime guards to warn when called without a current instance or after mount. Control flow in apiInject.ts is adjusted to use early guards and proceed with provides updates only when a current instance exists.

Changes

Cohort / File(s) Summary
Runtime DI guard adjustments
packages/runtime-core/src/apiInject.ts
Updated provide() to guard and warn in DEV when there is no current instance or when called after mount; refactored control flow to early-guard and proceed only when currentInstance exists.
Tests for incorrect usage warnings
packages/runtime-core/__tests__/apiInject.spec.ts
Added a “warnings for incorrect usage” suite with tests ensuring warnings for using inject/provide outside setup, provide in render, and provide within onMounted; imported onMounted for tests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant CompInstance as ComponentInstance
  participant Runtime as provide()
  participant DI as Provides Map

  Caller->>Runtime: provide(key, value)
  Runtime->>CompInstance: get currentInstance
  alt No currentInstance
    note over Runtime: __DEV__ warn: "provide() can only be used inside setup."
    Runtime-->>Caller: return (no mutation)
  else Has currentInstance
    alt Instance is mounted
      note over Runtime: __DEV__ warn: "provide() should not be called after mount."
      %% Proceed despite warning
    end
    Runtime->>DI: ensure current provides (possibly Object.create(parent))
    Runtime->>DI: set key = value
    Runtime-->>Caller: done
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I twitch my ears at warnings bright,
“Provide with care, and set up right!”
In burrows deep, the keys now flow,
From root to kits, the values go.
I thump—tests pass! My tail’s alight,
A carrot toast to guards in flight. 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The linked issue #13921 requests a functional fix to ensure that when provide is called during or after rendering, descendant components correctly inherit the updated values; however, this PR only adds warnings and tests without altering provide’s behavior or the inheritance mechanism, leaving the propagation bug unresolved. Implement the actual inheritance propagation fix by modifying provide to recreate or update the prototype chain for provides during post-render calls so that grandchildren receive the updated values, in addition to emitting warnings.
Out of Scope Changes Check ⚠️ Warning The PR introduces new tests and imports for warning scenarios such as using provide inside onMounted, in render functions, or with inject outside of setup, which do not relate to the linked issue’s goal of fixing dependency injection inheritance during post-render updates. These additions extend test coverage beyond the scope of correcting the inheritance bug described in #13921. Remove or relocate the unrelated warning tests into a separate PR focused on API usage linting and ensure this PR exclusively addresses the inheritance propagation bug to maintain clear scope alignment.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “fix(provide): warn when using provide after mounting” succinctly captures the core change of the pull request by indicating that a warning will now be emitted if provide is invoked post-mount, matching the primary modification in the code. It is concise, focused on the main behavior change, and avoids extraneous detail, making it clear to reviewers what the PR addresses.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8aa0b and ad3cb91.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/apiInject.spec.ts (2 hunks)
  • packages/runtime-core/src/apiInject.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/runtime-core/__tests__/apiInject.spec.ts (2)
packages/runtime-core/src/apiInject.ts (2)
  • inject (47-85)
  • provide (10-34)
packages/runtime-core/src/index.ts (4)
  • inject (61-61)
  • provide (61-61)
  • h (109-109)
  • onMounted (49-49)
packages/runtime-core/src/apiInject.ts (2)
packages/runtime-core/src/component.ts (1)
  • currentInstance (711-711)
packages/runtime-core/src/index.ts (1)
  • warn (133-133)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Redirect rules
  • GitHub Check: Header rules
  • GitHub Check: Pages changed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 102 kB 38.6 kB 34.8 kB
vue.global.prod.js 160 kB 58.7 kB 52.2 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 46.7 kB 18.3 kB 16.7 kB
createApp 54.7 kB 21.3 kB 19.5 kB
createSSRApp 58.9 kB 23 kB 21 kB
defineCustomElement 60 kB 23 kB 21 kB
overall 68.8 kB 26.5 kB 24.2 kB

Copy link

pkg-pr-new bot commented Sep 30, 2025

Open in StackBlitz

@vue/compiler-core

npm i https://pkg.pr.new/@vue/compiler-core@13954

@vue/compiler-dom

npm i https://pkg.pr.new/@vue/compiler-dom@13954

@vue/compiler-sfc

npm i https://pkg.pr.new/@vue/compiler-sfc@13954

@vue/compiler-ssr

npm i https://pkg.pr.new/@vue/compiler-ssr@13954

@vue/reactivity

npm i https://pkg.pr.new/@vue/reactivity@13954

@vue/runtime-core

npm i https://pkg.pr.new/@vue/runtime-core@13954

@vue/runtime-dom

npm i https://pkg.pr.new/@vue/runtime-dom@13954

@vue/server-renderer

npm i https://pkg.pr.new/@vue/server-renderer@13954

@vue/shared

npm i https://pkg.pr.new/@vue/shared@13954

vue

npm i https://pkg.pr.new/vue@13954

@vue/compat

npm i https://pkg.pr.new/@vue/compat@13954

commit: ad3cb91

@edison1105 edison1105 added ready to merge The PR is ready to be merged. 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Oct 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dependency Injection inheritance fails when provided after grandchildren are rendered.
2 participants