Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PATTERN_KEY_COMPARE algorithm should be updated #46050

Open
unional opened this issue Jan 1, 2023 · 7 comments · May be fixed by #46068
Open

PATTERN_KEY_COMPARE algorithm should be updated #46050

unional opened this issue Jan 1, 2023 · 7 comments · May be fixed by #46068

Comments

@unional
Copy link

unional commented Jan 1, 2023

Version

19.3.1

Platform

all

Subsystem

No response

What steps will reproduce the bug?

https://nodejs.org/api/esm.html#resolver-algorithm-specification

The assertions: Assert: keyA ends with "/" or contains only a single "*".

is no longer correct as ESM supports file extensions, e.g.:

  • #a/b.js
  • ./foo/*.js

I have released pattern-key-compare for resolve.imports.

How often does it reproduce? Is there a required condition?

N/A

What is the expected behavior?

The spec should be adjusted.

Also, should expect only single * instead of allowing multiple *. But that's a breaking change.

What do you see instead?

N/A

Additional information

No response

@aduh95
Copy link
Contributor

aduh95 commented Jan 2, 2023

I'm not sure I understand what you mean, how is it not correct?

  • #a/b.js is not a pattern, so it's expected that it breaks the assertion I think.
  • ./foo/*.js contains only a single *, so the assertion passes.

Do you have example of valid patterns that break the assertion?

@unional
Copy link
Author

unional commented Jan 2, 2023

AFAIK this is used to sort the keys in the exports and imports field.
i.e. in https://nodejs.org/api/esm.html#resolver-algorithm-specification

PACKAGE_IMPORTS_EXPORTS_RESOLVE()
2. Let expansionKeys be the list of keys of matchObj containing only a single "*", sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.

And you can see many of the keys in https://nodejs.org/api/packages.html#package-entry-points does not satisfy this assertion. e.g.:

{
  "name": "my-package",
  "exports": {
    ".": "./lib/index.js",
    "./lib": "./lib/index.js",
    "./lib/*": "./lib/*.js",
    "./lib/*.js": "./lib/*.js",
    "./feature": "./feature/index.js",
    "./feature/*": "./feature/*.js",
    "./feature/*.js": "./feature/*.js",
    "./package.json": "./package.json"
  }
}

// ./node_modules/es-module-package/package.json
{
  "exports": {
    "./features/*.js": "./src/features/*.js"
  },
  "imports": {
    "#internal/*.js": "./src/internal/*.js"
  }
}

@unional
Copy link
Author

unional commented Jan 2, 2023

Also, maybe the wording is a bit ambiguous:

Assert: keyA ends with "/" or contains only a single "*".

Does it mean:

  • keyA (ends with "/") or (contains only a single "*"), or
  • keyA ends with ("/" or contains only a single "*")

I can understand it is probably the prior, but you can see that popular package resolve.exports got the wrong idea.

@unional
Copy link
Author

unional commented Jan 2, 2023

Let expansionKeys be the list of keys of matchObj containing only a single "*"

Reading this again, seems like the first assertion is not even needed, as the PATTERN_KEY_COMPARE is only used there in the whole algorithm. Maybe historical?

@aduh95
Copy link
Contributor

aduh95 commented Jan 2, 2023

Does it mean:

  • keyA (ends with "/") or (contains only a single "*"), or
  • keyA ends with ("/" or contains only a single "*")

I'm not a native English speaker, so maybe there are nuances I don't get, but I don't think "ends with contains only a single *" is valid grammar and I wouldn't know how to interpret it, so to me only the former proposal makes sense and the assertion is not ambiguous.

Let expansionKeys be the list of keys of matchObj containing only a single "*"

Reading this again, seems like the first assertion is not even needed, and the PATTERN_KEY_COMPARE is only used there in the whole algorithm. Maybe historical?

This was added in #39635 by @guybedford, maybe he can help here?

@guybedford
Copy link
Contributor

@unional I believe you're correct - the ends with "/" is legacy and can be removed at this point from the assertion.

@unional
Copy link
Author

unional commented Jan 2, 2023

Sounds good. thx @guybedford. I can open a PR and also update the respective code.

@unional unional linked a pull request Jan 3, 2023 that will close this issue
unional added a commit to unional/node that referenced this issue Jan 3, 2023
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 a pull request may close this issue.

3 participants