Skip to content

imports allows and ignores #name/ in package map #40579

@evanw

Description

@evanw

Version

v17.0.1

Platform

Darwin Evans-MacBook-Pro.local 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64

Subsystem

No response

What steps will reproduce the bug?

Here's a simple example:

$ cat test.mjs
import * as x from '#x'
console.log(x)

$ cat package.json
{
  "imports": {
    "#x": "#what/foo/y.mjs"
  }
}

$ cat node_modules/foo/y.mjs
export let y = true

$ node test.mjs
[Module: null prototype] { y: true }

Notice the bogus #what/ prefix that is being discarded by node.

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

Always

What is the expected behavior?

I expected path resolution to fail, at least according to the documented algorithm here: https://nodejs.org/api/esm.html#resolution-algorithm. From what I understand, it's supposed to go something like this:

  1. ESM_RESOLVE("#x", "file://.")
  2. PACKAGE_IMPORTS_RESOLVE("#x", "file://.", ["default"])
  3. PACKAGE_IMPORTS_EXPORTS_RESOLVE("#x", { "#x": "#what/foo/y.mjs" }, "file://.", true, ["default"])
  4. PACKAGE_TARGET_RESOLVE("file://.", "#what/foo/y.mjs", "", false, true, ["default"])
  5. PACKAGE_RESOLVE("#what/foo/y.mjs", "file://./")

At this point packageName should be "#what" and packageSubpath should be ./foo/y.mjs. That should then fail because there is no file called node_modules/#what/foo/y.mjs on the file system.

What do you see instead?

Somehow the #what/ prefix seems to be getting lost in the process which lets the remapping to #what/foo/y.mjs succeed. Specifically #what/foo/y.mjs behaves just like foo/y.mjs. If I'm reading the algorithm correctly, then I think node's implementation is diverging from the specification somewhere and is incorrect.

Additional information

This looks like a bug in node to me. But if it's not, it would be great to update the documentation so that other implementations of node's algorithm can be implemented correctly. I'm trying to get the module resolution algorithm in esbuild to match node and I'm not sure what to do here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    esmIssues and PRs related to the ECMAScript Modules implementation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions