Skip to content

Conversation

robhogan
Copy link
Contributor

@robhogan robhogan commented Mar 20, 2025

Summary:
Currently, metro-resolver will break if an exports map includes a pattern key whose target does not have exactly one * character.

This is an incorrect limitation according to the spec - values may have any number (including zero) * characters (keys must have no more than one). The spec requires that all occurrences of * in the matched target are replaced with the patternMatch substring of the specified subpath.

Worse, we break rather than continue on such an "invalid" target, which means the presence of one of these targets can mean we fail resolution before other keys in the export map are tried.

This diff implements the spec:

https://nodejs.org/docs/latest/api/esm.html#resolution-algorithm-specification

If patternMatch is a String, then
Return PACKAGE_RESOLVE(target with every instance of "*" replaced by patternMatch, packageURL + "/").

 - **[Fix]**: Fix handling of export map targets with zero or 2+ wildcard characters in package.json imports/exports resolution

Reviewed By: huntie

Differential Revision: D70973129

fbshipit-source-id: 68632b68dbc37dc24988cd68529a5cebfcb5a5d3

Stack created with Sapling. Best reviewed with ReviewStack.

…ution (#1458)

Summary:
Pull Request resolved: #1458

Fix: #1457

`package.json#exports` resolution attempts, but currently fails, to order potential pattern keys (exports map keys containing `'*'`) by specificity, due to an invalid comparator function passed to `sort()`.

This fixes the comparison according to the specification in https://nodejs.org/api/esm.html#resolution-algorithm-specification - ie, longest prefix before `'*'`, then by longest key overall.

Changelog:
```
 - **[Fix]**: Fix wildcard pattern precedence in package.json imports/exports resolution
```

Reviewed By: huntie

Differential Revision: D70892462

fbshipit-source-id: 41c1de662a505ef2f56f4a8731f851ba48eaa50c
…ports resolution

Summary:
Currently package exports resolution pattern matching may falsely match some patterns because we don't apply a subtle part of the [specification](https://nodejs.org/docs/latest/api/esm.html#resolution-algorithm-specification) - specifically, we check that the subpath starts with the pattern base and ends with the pattern trailer, but not that the subpath length >= the pattern length.

This means the `startsWith` and `endsWith` checks may both be satisfied by the same substring, e.g:

```
  "exports": {
    "./repeated*/repeated": null
  }
```

Will incorrectly match the substring `./repeated`, because it both starts with `./repeated` and ends with `/repeated`.

The spec would disallow this because `matchKey` is shorter than `patternKey`:

> If `patternTrailer` has zero length, or if `matchKey` ends with `patternTrailer` and the length of `matchKey` is greater than or equal to the length of `expansionKey`, then:
Let `target` be the value of `matchObj[expansionKey]`.
...

This diff applies that bit of the spec.

```
 - **[Fix]**: Fix edge-case overmatching of pattern keys in package.json exports/imports resolution.
```

Reviewed By: huntie

Differential Revision: D70971859

fbshipit-source-id: d3a3c317234bd015b58b7ac784aa5ac8f7c48d5e
…s in package.json imports/exports resolution

Summary:
Currently, metro-resolver will break if an exports map includes a pattern key whose target does not have exactly one `*` character.

This is an incorrect limitation according to the spec - values may have any number (including zero) `*` characters (*keys* must have no more than one). The spec requires that *all* occurrences of `*` in the matched target are replaced with the `patternMatch` substring of the specified subpath.

Worse, we *`break`* rather than `continue` on such an "invalid" target, which means the presence of one of these targets can mean we fail resolution before other keys in the export map are tried.

This diff implements the spec:

[https://nodejs.org/docs/latest/api/esm.html#resolution-algorithm-specification](https://nodejs.org/docs/latest/api/esm.html#resolution-algorithm-specification)

> If `patternMatch` is a `String`, then
> Return **`PACKAGE_RESOLVE`**(`target` with every instance of "*" replaced by `patternMatch`, `packageURL + "/"`).

```javascript
 - **[Fix]**: Fix handling of export map targets with zero or 2+ wildcard characters in package.json imports/exports resolution
```

Reviewed By: huntie

Differential Revision: D70973129

fbshipit-source-id: 68632b68dbc37dc24988cd68529a5cebfcb5a5d3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants