fix(arborist): link meta-only optional peers in linked strategy#9461
Merged
owlstronaut merged 1 commit intoJun 3, 2026
Merged
Conversation
owlstronaut
approved these changes
Jun 3, 2026
Contributor
|
🎉 Backport to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In continuation of our exploration of using
install-strategy=linkedin the Gutenberg monorepo, which powers the WordPress Block Editor.Under
install-strategy=linked, an optional peer dependency declared only inpeerDependenciesMeta(with no matching entry inpeerDependencies) was not linked into the dependent's isolatednode_modules, even when an ancestor in the graph provided it.For example
@emotion/reactdeclaresreactinpeerDependenciesand@types/reactonly inpeerDependenciesMeta; after a linked install its storenode_modulescontainedreactbut not@types/react, so its shipped.d.tscould not resolve the React typings under strict isolation and the breakage cascaded into consumers as TypeScript errors.The root cause is that npm only creates dependency edges from
peerDependencies.A peer named only in
peerDependenciesMetagets no edge at all.The isolated reifier materializes a dependency into a package's store
node_modulesonly when the package has a resolved edge for it (edge.to.target), so the meta-only optional peer was silently dropped.Required peers (and optional peers that also appear in
peerDependencies) have edges and were materialized correctly; meta-only optional peers were the gap.This PR resolves the gap in
#assignCommonPropertiesinisolated-reifier.js.After the edge-derived dependency lists are built, it iterates
peerDependenciesMeta, and for each optional entry that is not already a dependency it resolves the name against the tree vianode.resolve()and, when found, materializes it as an optional store dependency.Because the peer is added to the package's store dependency set, the store instance's hash is keyed by it, and it resolves to the same instance the consumer uses rather than a duplicate copy.
If no ancestor provides the peer,
node.resolve()returns nothing and it stays omitted, preserving optional semantics.References
Fixes #9460