denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.28k stars 5.36k forks source link

node worker_threads --conditions bug (vitest breaks for solidjs) #26567

Open birkskyum opened 1 week ago

birkskyum commented 1 week ago

Version: Deno 2.0.3

Repro:

Vitest 1.6.0

Error:

Deno fails - vitest 1.6.0 ``` ➜ deno task test Task test vitest run RUN v1.6.0 ❯ src/components/Counter.test.tsx (1 test | 1 failed) 4ms ❯ src/components/Counter.test.tsx > > increments value → Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with . ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ FAIL src/components/Counter.test.tsx > > increments value Error: Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with . ❯ notSup node_modules/.deno/solid-js@1.9.3/node_modules/solid-js/web/dist/server.js:1136:9 ❯ Module.render node_modules/.deno/@solidjs+testing-library@0.8.10/node_modules/@solidjs/testing-library/dist/index.js:55:65 53| } 54| }) : wrappedUi; 55| const dispose = hydrate ? solidHydrate(routedUi, container) : solidRender(routedUi, container); | ^ 56| mountedContainers.add({ container, dispose }); 57| const queryHelpers = getQueriesForElement(container, queries); ❯ src/components/Counter.test.tsx:8:29 ❯ eventLoopTick ext:core/01_core.js:175:7 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ Test Files 1 failed (1) Tests 1 failed (1) Start at 18:34:34 Duration 927ms (transform 71ms, setup 67ms, collect 184ms, tests 4ms, environment 302ms, prepare 80ms) ```

Now trying to run in same folder with npm run test, bun run test or node --run test (Node 22) does work

Npm works - vitest 1.6.0 ```sh ➜ npm run test > test > vitest run RUN v1.6.0 ✓ src/components/Counter.test.tsx (1) ✓ (1) ✓ increments value Test Files 1 passed (1) Tests 1 passed (1) Start at 18:36:43 Duration 566ms (transform 72ms, setup 45ms, collect 152ms, tests 39ms, environment 189ms, prepare 43ms) ```

Vitest 2.1.3 - Same thing

Tried updating the Vitest to 2.x "vitest": "^2.0.0" (upstream PR), and it's the same result:

Deno fails - vitest 2.1.3 ``` ➜ deno task test Task test vitest run RUN v2.1.3 ❯ src/components/Counter.test.tsx (1) ❯ (1) × increments value ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ FAIL src/components/Counter.test.tsx > > increments value Error: Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with . ❯ notSup node_modules/.deno/solid-js@1.9.3/node_modules/solid-js/web/dist/server.js:1136:9 ❯ Module.render node_modules/.deno/@solidjs+testing-library@0.8.10/node_modules/@solidjs/testing-library/dist/index.js:55:65 53| } 54| }) : wrappedUi; 55| const dispose = hydrate ? solidHydrate(routedUi, container) : solidRender(routedUi, container); | ^ 56| mountedContainers.add({ container, dispose }); 57| const queryHelpers = getQueriesForElement(container, queries); ❯ src/components/Counter.test.tsx:8:29 ❯ Object.runMicrotasks ext:core/01_core.js:672:26 ❯ processTicksAndRejections ext:deno_node/_next_tick.ts:57:10 ❯ runNextTicks ext:deno_node/_next_tick.ts:74:3 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ Test Files 1 failed (1) Tests 1 failed (1) Start at 19:01:16 Duration 861ms (transform 80ms, setup 98ms, collect 201ms, tests 3ms, environment 332ms, prepare 48ms) ```

with npm it works

Npm works - vitest 2.1.3 ``` ➜ npm run test > test > vitest run RUN v2.1.3 (node:99528) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead. (Use `node --trace-deprecation ...` to show where the warning was created) stdout | src/components/Counter.test.tsx > > increments value TESTVAR: undefined ✓ src/components/Counter.test.tsx (1) ✓ (1) ✓ increments value Test Files 1 passed (1) Tests 1 passed (1) Start at 19:01:39 Duration 709ms (transform 82ms, setup 75ms, collect 139ms, tests 35ms, environment 201ms, prepare 73ms) ```
marvinhagemeister commented 6 days ago

Looking into this, all things point to a resolution error with import conditions of an npm package. We're loading solid-js/dist/server.js whereas Node never loads this. Like most frameworks solid resolves to a different entry for server-side rendering compared to rendering in the browser. For some reason we're pulling in the browser render code. Not yet sure why.

marvinhagemeister commented 6 days ago

Found the root problem and was able to create a minimal reproduction case. The issue is that we're ignoring the execArgv argument passed to Workers from Node's worker_threads. Node has a --conditions argument which allows you to override the export conditions to pick in package.json. Vitest and by extension the solid testing library overrides that so that it will pick a specific entry when importing solid-js/web in a test suite.

Minimal reproduction

  1. Clone https://github.com/marvinhagemeister/deno-worker-condition
  2. Run deno run -A main.mjs