Skip to content

Conversation

@hi-ogawa
Copy link
Contributor

@hi-ogawa hi-ogawa commented Jan 27, 2024

Description

Follow up of #5045 (review)

It turned out the "non throwing" behavior of import.meta.resolve is only for path based import such as ./bad-path.js but not for bad-package. For the first case, Vitest throws an error during readFileSync while NodeJS still throws ERR_MODULE_NOT_FOUND, so this is a potential inconsistency, but I suppose it's very unlikely that this difference would affect Vitest user in any critical way.
Nonetheless, I'll see if there is a way to align the behavior closer to NodeJS instead of surfacing "readFileSync" exception.

references

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

@netlify
Copy link

netlify bot commented Jan 27, 2024

Deploy Preview for fastidious-cascaron-4ded94 canceled.

Name Link
🔨 Latest commit 315325e
🔍 Latest deploy log https://app.netlify.com/sites/fastidious-cascaron-4ded94/deploys/65b84e6518830d00082ccaeb

@hi-ogawa hi-ogawa changed the title fix(vm): uniform import error when module is not found fix(vm): improve error when module is not found during vm execution Jan 28, 2024
@hi-ogawa hi-ogawa marked this pull request as ready for review January 28, 2024 03:31
@hi-ogawa hi-ogawa changed the title fix(vm): improve error when module is not found during vm execution fix(vm): improve error when module is not found Jan 28, 2024
@sheremet-va
Copy link
Member

I suppose it's very unlikely that this difference would affect Vitest user in any critical way

I think this is a popular way to import package and fallback when it's not installed. Something like this:

try {
  import('name')
} catch(err) {
  if(err.code === 'ERR_MODULE_NOT_FOUND') {
    // fallback
  }
  throw err
}

// check file since latest NodeJS's import.meta.resolve doesn't throw on non-existing path
if (type === 'module' || type === 'commonjs') {
if (!existsSync(path))
throw new Error(`[vitest:vm] Cannot find module '${path}'`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer throwing the same error that Node does. Is there any reason not to do that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me. I made a different error so that the test shows the difference, but there's no reason to not align with Node.

@hi-ogawa
Copy link
Contributor Author

hi-ogawa commented Jan 28, 2024

I think this is a popular way to import package and fallback when it's not installed. Something like this:

try {
  import('name')
} catch(err) {
  if(err.code === 'ERR_MODULE_NOT_FOUND') {
    // fallback
  }
  throw err
}

Actually this pattern seems not affected. For the bare package name, import.meta.resolve("name") is still throwing ERR_MODULE_NOT_FOUND (I don't know, maybe NodeJS changes this behavior later, but at least this seems conscious decision as indicated by the test in nodejs/node#49038). What doesn't get thrown is anything with namespace (including file:// which is the result of relative case import.meta.resolve("./name")). This actually include something like node:something, so probably we should mimic the same error with code: ERR_MODULE_NOT_FOUND like you suggested.

sheremet-va
sheremet-va previously approved these changes Jan 29, 2024
@hi-ogawa
Copy link
Contributor Author

I was checking with a different version of node and it looks there was another change around v20.2.0 -> v20.3.0. It doesn't look like this change is documented in https://nodejs.org/api/esm.html#importmetaresolvespecifier, but probably this is a related PR on Node:

# I use volta https://github.com/volta-cli/volta to switch local node version
#   volta pin [email protected]
$ node --version
v20.2.0

$ pnpm -C test/vm-threads test not-found.test.ts

...

 FAIL  test/not-found.test.ts > namespace
AssertionError: expected Error: Only URLs with a scheme in: file a… { …(2) } to match object { code: 'ERR_MODULE_NOT_FOUND', …(1) }

- Expected
+ Received

- Object {
-   "code": "ERR_MODULE_NOT_FOUND",
-   "message": "Cannot find module 'non-existing-namespace:xyz'",
- }
+ [Error: Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol 'non-existing-namespace:']

 ❯ test/not-found.test.ts:30:3
     28| 
     29| it('namespace', async () => {
     30|   await expect(() => notFound.importNamespace()).rejects.toMatchObject({
       |   ^
     31|     code: 'ERR_MODULE_NOT_FOUND',
     32|     message: 'Cannot find module \'non-existing-namespace:xyz\'',

Is it fine to keep this error for old node version?

@sheremet-va
Copy link
Member

Is it fine to keep this error for old node version?

We don't use the default ESM loader (we don't even support loaders in VM), so I'd say it is fine to have the error we have today.

@sheremet-va sheremet-va merged commit 79a50c3 into vitest-dev:main Feb 6, 2024
@sheremet-va sheremet-va added this to the 1.3.0 milestone Feb 9, 2024
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