Skip to content

fix(di): share the injection context across duplicated CLI copies - #6121

Closed
edusperoni wants to merge 1 commit into
mainfrom
fix/cross-copy-injection-context
Closed

fix(di): share the injection context across duplicated CLI copies#6121
edusperoni wants to merge 1 commit into
mainfrom
fix/cross-copy-injection-context

Conversation

@edusperoni

Copy link
Copy Markdown
Collaborator

PR Checklist

What is the current behavior?

The injection context (inject()'s hidden current slot) is a module-local variable. Node caches modules per resolved path, so when a hook or extension module resolves a different copy of the CLI than the one running — a nested nativescript install in an extension's tree, or a project-local copy under a globally-run CLI — that copy's inject() reads its own dead slot and throws "inject() can only be called from an injection context", even though the author is synchronously inside run() in a perfectly valid context. Verified in review with a realistic duplicated-copy install; it breaks the documented flagship examples of the stacked API PRs.

What is the new behavior?

The context lives on globalThis under a Symbol.for key, so every loaded copy shares one slot — in the single-copy world the behavior is byte-identical. When a copy serves inject() through a frame it did not set (i.e. a duplicated copy is in play), it warns once, naming its own path and pointing at the fix: duplicated copies work but load the CLI twice; peerDependency on nativescript lets the running copy be shared. This keeps the ecosystem nudged toward the single-copy/local-install direction while making the documented API true in every install layout that exists today.

Tests include a genuine second-copy scenario: inject.js has no runtime imports, so a copied file loaded from another path is a real second module instance — it resolves through the running copy's context and produces exactly one warning.

Full suite green; no behavior change when a single copy is loaded.

The context slot was module-local, so a hook or extension module that
resolves a different copy of the CLI than the one running (a nested
nativescript install, or a project-local copy under a globally-run CLI)
got a dead slot and inject() threw despite being synchronously inside a
valid context. The slot now lives on globalThis under a Symbol.for key,
and a copy serving inject() through a frame it did not set warns once,
naming its path - the duplicated copy works but loads the CLI twice,
and peerDependencies avoid it.

The second-copy test loads a genuinely separate module instance:
inject.js has no runtime imports, so a copied file is the real
duplicated-copy situation.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3af2e869-3197-4da7-84cf-51809581e5ca

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@edusperoni

Copy link
Copy Markdown
Collaborator Author

Landed directly on main as b52b8e0.

@edusperoni edusperoni closed this Aug 5, 2026
@edusperoni
edusperoni deleted the fix/cross-copy-injection-context branch August 5, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant