Skip to content

fix: preserve order in packageRegistryData using IndexMap#86

Merged
Boshen merged 1 commit intoyarnpkg:mainfrom
leegeunhyeok:fix/preserve-order-in-package-registry-data
Jan 14, 2026
Merged

fix: preserve order in packageRegistryData using IndexMap#86
Boshen merged 1 commit intoyarnpkg:mainfrom
leegeunhyeok:fix/preserve-order-in-package-registry-data

Conversation

@leegeunhyeok
Copy link
Contributor

@leegeunhyeok leegeunhyeok commented Jan 6, 2026

Description

The packageRegistryData is structured as a nested array where order is guaranteed.

However, during deserialization of the PnP manifest via serde_json, it's being mapped to FxHashMap, which doesn't preserve the array's original order.

While this works in most cases, it becomes problematic when SOFT-linked dependencies (e.g., virtual packages) are present. In such scenarios, the resolution must respect the order of packageRegistryData to correctly resolve HARD-linked actual dependencies.

In my case, the following PnP manifest data existed (added as a test case):

Scenario: Trying to resolve invariant from react-native@npm:0.72.6

Ref: package.json dependencies of react-native ("invariant": "^2.2.4" package listed correctly)

The sample data below assumes react-native -> lib, invariant -> inner-package.

[
  ["lib", [
    ["npm:1.0.0", { // 👈 This dependency should resolve to the HARD-linked dependency referenced by the `virtual:3dd9...` locator
      "packageLocation": "./.yarn/unplugged/lib-virtual-35bde7b160/node_modules/lib/",
      "packageDependencies": [
        ["lib", "npm:1.0.0"] // ❌ `inner-package` can not be resolved here
      ],
      "linkType": "SOFT"
    }],
   ["virtual:3dd9e658478cd3cd949702eb8109c115b53d3cccb220009afea78128ac0aecb3aff90d8fc0444dda495e2e53ec6878a7220167f13b9b83d168217b139fe65def#npm:1.0.0", { // 👈 Here!
      "packageLocation": "./.yarn/unplugged/lib-virtual-35bde7b160/node_modules/lib/",
      "packageDependencies": [
        ["inner-package", "npm:1.0.0"], // ✅ From this locator, we can resolve `inner-package`
        ["lib", "virtual:3dd9e658478cd3cd949702eb8109c115b53d3cccb220009afea78128ac0aecb3aff90d8fc0444dda495e2e53ec6878a7220167f13b9b83d168217b139fe65def#npm:1.0.0"]
      ],
      "linkType": "HARD"
    }]
  ]],
  ["inner-package", [
    ["npm:1.0.0", {
      "packageLocation": "./path/to/inner-package/",
      "packageDependencies": [],
      "linkType": "SOFT"
    }]
  ]]
]

The lib package had inner-package as a dependency, but pnp-rn returned a SOFT-linked virtual locator, causing a failure to resolve inner-package. This issue occurred because the order of the PnP manifest data was not respected.

To work correctly, entries must be inserted into the Trie following the packageRegistryData order: lib@npm:1.0.0, lib@virtual:3dd9.... FxHashMap doesn't preserve this order, inserting entries arbitrarily based on hash values. This causes pnp-rs to return SOFT-linked locators instead of HARD-linked packages when SOFT entries are processed out of order, leading to incorrect resolution results.

To address this issue, FxHashMap is replaced with IndexMap to preserve the order of data in the PnP manifest, and test cases are added to verify this behavior.

(Before)

The insertion order of Trie data differs from the actual PnP manifest data.

스크린샷 2026-01-07 오전 1 14 50

(After)
스크린샷 2026-01-07 오전 1 13 14

Test Results

cargo test --package pnp --lib -- lib_tests::tests::test_package_registry_data_order --exact
image

@Boshen Boshen self-requested a review January 7, 2026 09:25
@Boshen Boshen self-assigned this Jan 7, 2026
@Boshen Boshen merged commit eae43ad into yarnpkg:main Jan 14, 2026
6 checks passed
@github-actions github-actions bot mentioned this pull request Jan 14, 2026
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.

2 participants