Repository navigation
Resolver: Fall through unmatched nested conditions - #2074
Merged
robhogan merged 3 commits intoOct 17, 2026
Merged
Conversation
Metro treats `null` and `undefined` as equivalent, so signalling an unmatched nested condition with `undefined` (as distinct from an explicit `null` exclusion) needed a `lint/strictly-null` suppression. Return a module-level `NO_MATCH` symbol instead. Unlike a string sentinel, it can't collide with a literal target in `package.json`. At the top level, any non-string result is stored as `null`, so an exact key with no matching condition is still retained and takes precedence over subpath patterns. Changelog: [Internal]
Collaborator
|
Looks good, thanks @maximilliangrand ! I've pushed a couple of small changes:
A possible follow-up is the still-incorrect handling of arrays - if we support them at all we should align with Node. Thanks again |
robhogan
approved these changes
Oct 17, 2026
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.
Summary
Metro stops resolving conditions after entering a matching parent, even when none of that parent's nested conditions match. For example, with
react-nativeasserted and a CommonJS import, this export fails instead of selecting./fallback.js:{ "exports": { "./feature": { "react-native": {"import": "./feature.mjs"}, "default": "./fallback.js" } } }Resolve nested conditions recursively and continue to the next parent condition only when the nested object has no matching target. This follows Node's nested-condition semantics and applies to both
exportsandimports. Explicitnullexclusions and invalid targets stop resolution; unmatched exact subpaths retain precedence over wildcard patterns. Numeric and boolean targets report invalid package configuration, and unsupported nested arrays retain their blocked behavior.Changelog: [Fix] Resolve parent fallback conditions when a nested package exports or imports condition has no matching target
AI-assisted implementation and testing.
Test plan
On macOS with Node.js 26.7.0 and the frozen Yarn lockfile:
node node_modules/jest/bin/jest.js packages/metro-resolver/src/__tests__/package-exports-test.js packages/metro-resolver/src/__tests__/package-imports-test.js --runInBand— all 77 tests passed. Cases cover unmatched, empty, and deeper nested objects; later named/default conditions; null exclusions; invalid strings/numbers/booleans; and unsupported nested arrays.node node_modules/jest/bin/jest.js packages/metro-resolver --runInBand— 145 tests and 14 snapshots passed.node node_modules/jest/bin/jest.js --ci --maxWorkers 4— 158 suites, 2,956 tests, and 487 snapshots passed; 14 tests skipped.node node_modules/flow-bin/cli.js check --timeout 90— no errors.node node_modules/eslint/bin/eslint.js . --cacheandnode node_modules/prettier/bin/prettier.cjs --check .— passed.yarn run build,yarn run typecheck-ts, andyarn run test-smoke— passed.The fallback, null, and invalid-target expectations were also checked against Node.js resolution using temporary packages. Node supports additional array shapes that Metro already treats as unsupported; this change preserves Metro's existing array behavior. Windows/Linux and other Node versions were not run locally.