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

Vitest crashing in Yarn PnP mode when using happy-dom or jsdom environment and Yarn workspaces #4413

Closed
6 tasks done
wojtekmaj opened this issue Oct 31, 2023 · 17 comments · Fixed by #4698
Closed
6 tasks done
Labels
p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@wojtekmaj
Copy link
Contributor

wojtekmaj commented Oct 31, 2023

Describe the bug

When running a really basic test (irrelevant to reproduction), when using happy-dom or jsdom environment and Yarn workspaces, the following error appears:

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
{ type: 'Unhandled Error', stacks: [] }

I dug down the issue and actually caught it in tinypool catch:

image

And now we got somewhere:

ERROR Error: local-pkg tried to access happy-dom, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

Required package: happy-dom (via "happy-dom/package.json")
Required by: local-pkg@npm:0.4.3 (via /Users/wmaj/.yarn/berry/cache/local-pkg-npm-0.4.3-de61dda1fd-10c0.zip/node_modules/local-pkg/index.mjs)

    at makeError (/Users/wmaj/Projekty/vitest-pnp/.pnp.cjs:16978:34)
    at resolveToUnqualified (/Users/wmaj/Projekty/vitest-pnp/.pnp.cjs:18648:21)
    at Object.resolveToUnqualified (/Users/wmaj/Projekty/vitest-pnp/pnp.cjs:18828:26)
    at resolve$1 (file:///Users/wmaj/Projekty/vitest-pnp/.pnp.loader.mjs:1985:31)
    at nextResolve (node:internal/modules/esm/hooks:833:28)
    at Hooks.resolve (node:internal/modules/esm/hooks:278:30)
    at handleMessage (node:internal/modules/esm/worker:168:24)
    at checkForMessages (node:internal/modules/esm/worker:117:28)
    at process.<anonymous> (node:internal/modules/esm/worker:136:5)
    at process.emit (node:events:514:28)

I tracked down the issue to ensurePackageInstalled function, and here's the full trace that leads to the issue above:

Trace
    at ensurePackageInstalled (file:///Users/wmaj/Projekty/vitest-pnp/.yarn/unplugged/vitest-virtual-4272a18581/node_modules/vitest/dist/vendor-node.a7c48fe1.js:153:13)
    at startVitest (file:///Users/wmaj/Projekty/vitest-pnp/.yarn/unplugged/vitest-virtual-4272a18581/node_modules/vitest/dist/vendor-node.a7c48fe1.js:21194:13)
    at async start (file:///Users/wmaj/Projekty/vitest-pnp/.yarn/unplugged/vitest-virtual-4272a18581/node_modules/vitest/dist/cli.js:135:17)
    at async CAC.run (file:///Users/wmaj/Projekty/vitest-pnp/.yarn/unplugged/vitest-virtual-4272a18581/node_modules/vitest/dist/cli.js:99:3)

and further to:

antfu-collective/local-pkg#2

I worked around this issue by quickly patching ensurePackageInstalled:

async function ensurePackageInstalled(dependency, root) {
+  if (process.versions.pnp) {
+    // Better than crashing I guess
+    return true;
+  }

But this didn't make the error go away 🫠 Another issue causing the same { type: 'Unhandled Error', stacks: [] } output appeared.

I again tracked it down, this time to importModule call, also from local-pkg.

When patched like so:

function importModulePnp(request) {
  if (process.versions.pnp) {
    return import(request);
  }

  return importModule(request);
}

the tests went all green. PHEW!

Reproduction

vitest-pnp.zip

Unzip

yarn
cd submodule
yarn vitest run

What I found especially surprising is that without submodule thing, installing and calling vitest on the root level, it doesn't break.

System Info

System:
    OS: macOS 14.1
    CPU: (8) arm64 Apple M2
    Memory: 21.33 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.9.0 - /private/var/folders/3y/swkjq1x101b76mzjgt4pm2d80000gp/T/xfs-9f5c4b9a/node
  Browsers:
    Edge: 118.0.2088.76
    Safari: 17.1

Used Package Manager

yarn

Validations

@sheremet-va
Copy link
Member

Looks like this is a duplicate of #899

@wojtekmaj
Copy link
Contributor Author

Shoot! It looks like one indeed. I hope however that the research, workarounds, and reproducible repo will come in handy.

@sheremet-va sheremet-va added bug p3-minor-bug An edge case that only affects very specific usage (priority) and removed pending triage labels Oct 31, 2023
@robinelvin
Copy link

Similar issue here. Running tests using vitest in a "node" environment works but running with "jsdom" stops with the following:

Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL
 ❯ makeError ../../.pnp.cjs:36106:34
 ❯ applyNodeExportsResolution ../../.pnp.cjs:37438:13
 ❯ resolveUnqualifiedExport ../../.pnp.cjs:37824:35
 ❯ resolveRequest ../../.pnp.cjs:37909:106
 ❯ Object.resolveRequest ../../.pnp.cjs:37966:26
 ❯ resolve$1 ../../.pnp.loader.mjs:1997:21

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_INVALID_ARG_TYPE', pnpCode: 'EXPORTS_RESOLUTION_FAILED', data: { unqualifiedPath: '/Users/rob/Projects/Elixir/core-develop/.yarn/cache/@vitest-runner-npm-0.34.6-dae9162b5c-3525d8e4f8.zip/node_modules/@vitest/runner/utils', locator: { name: '@vitest/runner', reference: 'npm:0.34.6' }, pkgJson: { name: '@vitest/runner', type: 'module', version: '0.34.6', description: 'Vitest test runner', license: 'MIT', funding: 'https://opencollective.com/vitest', homepage: 'https://github.com/vitest-dev/vitest/tree/main/packages/runner#readme', repository: { type: 'git', url: 'git+https://github.com/vitest-dev/vitest.git', directory: 'packages/runner' }, bugs: { url: 'https://github.com/vitest-dev/vitest/issues' }, sideEffects: true, exports: { '.': { types: './dist/index.d.ts', import: './dist/index.js' }, './utils': { types: './dist/utils.d.ts', import: './dist/utils.js' }, './types': { types: './dist/types.d.ts', import: './dist/types.js' }, './*': './*' }, main: './dist/index.js', module: './dist/index.js', types: './dist/index.d.ts', files: [ 'dist', '*.d.ts' ], dependencies: { 'p-limit': '^4.0.0', pathe: '^1.1.1', '@vitest/utils': '0.34.6' }, scripts: { build: 'rimraf dist && rollup -c', dev: 'rollup -c --watch' } }, subpath: 'utils', conditions: { constructor: 'Function<Set>', has: 'Function<has>', add: 'Function<add>', delete: 'Function<delete>', clear: 'Function<clear>', entries: 'Function<entries>', forEach: 'Function<forEach>', size: 3, values: 'Function<values>', keys: 'Function<values>' }, request: '@vitest/runner/utils', issuer: '/Users/rob/Projects/Elixir/core-develop/.yarn/__virtual__/vitest-virtual-68e5eaf46b/0/cache/vitest-npm-0.34.6-48e1d6f80a-0191422ab9.zip/node_modules/vitest/dist/index.js' } }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

I think this is due to the dynamic import inside vitest here

@sheremet-va
Copy link
Member

This is because node‘s URL is overriden by jsdom URL

@robinelvin
Copy link

This is because node‘s URL is overriden by jsdom URL

Ok, so is there a fix or workaround?

@sheremet-va
Copy link
Member

You can override URL in setup files:

import { URL } from 'node:url'
globalThis.URL = URL

This might break some JSDOM API.

@robinelvin
Copy link

@sheremet-va Unfortunately this doesn't work. vitest crashes with the error before the setup files are executed. Additionally, it can't be added to the global setup or the vitest config.

I don't quite understand why this hack is required since it works perfectly well if using the normal node_modules mode.

@sheremet-va
Copy link
Member

I guess it uses global URL which is overriden by jsdom and incompatible with "path" module (url parser was updated in Node bot so long ago)

@robinelvin
Copy link

Contrary to what this ticket is about I have switched to happy-dom by defining the dependency in .yarnrc.yml and changing the test file comment header. My tests now work.

packageExtensions:
  local-pkg@*:
    peerDependencies:
      "happy-dom": "*"

@randompixel
Copy link

I am getting the same error as #4413 (comment)

 FAIL  tests/unit/services/browserCheck.test.js [ tests/unit/services/browserCheck.test.js ]
Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL
 ❯ makeError .pnp.cjs:25457:34
 ❯ applyNodeExportsResolution .pnp.cjs:26789:13
 ❯ resolveUnqualifiedExport .pnp.cjs:27175:35
 ❯ resolveRequest .pnp.cjs:27260:106
 ❯ Object.resolveRequest .pnp.cjs:27317:26
 ❯ resolve$1 .pnp.loader.mjs:2019:21

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_INVALID_ARG_TYPE', pnpCode: 'EXPORTS_RESOLUTION_FAILED', data: { unqualifiedPath:
....

However this appears to only affect 0.34.6. If I downgrade to vitest 0.34.5 then the tests work fine.

Using Yarn 4.0.2 with PNP. Vite 4.5.0

@Michle99
Copy link

Michle99 commented Dec 12, 2023

I am getting the same error as #4413 (comment)

 FAIL  src/__tests__/App.test.tsx [ src/__tests__/App.test.tsx ]
Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL
 ❯ makeError .pnp.cjs:14195:34
 ❯ applyNodeExportsResolution .pnp.cjs:15527:13
 ❯ resolveUnqualifiedExport .pnp.cjs:15913:35
 ❯ resolveRequest .pnp.cjs:15998:106
 ❯ Object.resolveRequest .pnp.cjs:16055:26
 ❯ resolve$1 .pnp.loader.mjs:2019:21

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_INVALID_ARG_TYPE', pnpCode: 'EXPORTS_RESOLUTION_FAILED', data: { unqualifiedPath: 
...

Using Yarn 4.0.2 with PnP, Vite 5.0.0, Vitest 1.0.4, jsdom 23.0.1.
Is there a fix for this issue?


Edit:
I changed the @testing-library/jest-dom to using happy-dom as @robinelvin mentioned. The tests works now with Yarn v4.0.2 with PnP.

@llowrey
Copy link

llowrey commented Dec 21, 2023

I created a yarn pull request to resolve this: yarnpkg/berry#6030

Well, the fix addresses this: Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL.

The issue appears to be that somewhere, global.URL is being replaced, perhaps by an implementation that's meant to be browser compatible. Since the URL instances are not those generated by the node url package calls to url.isURL() fail and a number of calls made inside .pnp.cjs therefore fail. The PR explicitly imports URL from url in order to ensure that all ops in .pnp.cjs use proper URL objects.

A quick fix is to replace all occurrences of new URL( with new url.URL( in .pnp.cjs. This can be achieved via:

sed -i 's/new URL/new url.URL/' .pnp.cjs

@DiFuks
Copy link

DiFuks commented Dec 27, 2023

In my case, it works on Node.js 20, but I encounter the same error on version 18

Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL

yarn 4.0.2, vite 5.0.10, vitest 1.0.2

@wojtekmaj
Copy link
Contributor Author

Thrilled to confirm version 1.1.1 fixed this issue for me!

@PilotConway
Copy link

I'm still having this issue with version 1.1.2. If I run at the monorepo root I still get { type: 'Unhandled Error', stacks: [] } and when I run in a specific package in my monorepo, I'm still seeing more detailed:

Error: The "path" argument must be of type string or an instance of URL. Received an instance of URL
Require stack:
- /Project/Path/.yarn/cache/aria-query-npm-5.3.0-76575ac83b-305bd73c76.zip/node_modules/aria-query/lib/elementRoleMap.js
- ...

I upgraded from 0.34 which was the last version that was working for us.

@sheremet-va
Copy link
Member

I'm still having this issue with version 1.1.2. If I run at the monorepo root I still get { type: 'Unhandled Error', stacks: [] } and when I run in a specific package in my monorepo, I'm still seeing more detailed

This error has nothing to do with this issue. Yarn uses a global URL which is replaced when using jsdom or happy-dom environment. Yarn should use URL from node:url module.

@PilotConway
Copy link

Ok, I can open another ticket then. We are using jsdom though.

@github-actions github-actions bot locked and limited conversation to collaborators Jan 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants