Skip to content

fix(core): split taskContext to remove node:async_hooks from browser bundle#1244

Merged
fi3ework merged 1 commit into
mainfrom
fix/task-context-browser-bundle
May 12, 2026
Merged

fix(core): split taskContext to remove node:async_hooks from browser bundle#1244
fi3ework merged 1 commit into
mainfrom
fix/task-context-browser-bundle

Conversation

@fi3ework

@fi3ework fi3ework commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

Background

CI refined at #1242.

@rstest/core/browser-runtime re-exported a shared taskContext module that used await import(asyncHooksSpecifier) with a /* webpackIgnore: true */ magic comment to lazy-load node:async_hooks. The variable specifier defeats Rspack's static analysis (the magic comment only applies to literal arguments), so node:async_hooks ended up in the browser bundle and any downstream consumer rebundling that chunk hits Critical dependency: the request of a dependency is an expression.

image

Implementation

  • Split taskContext.ts into a type-only contract (TaskContext) plus per-platform implementations: taskContext.node.ts with static import { AsyncLocalStorage } from 'node:async_hooks' and taskContext.browser.ts with a closure-only fallback.
  • Inject the impl via createRstestRuntime(workerState, { taskContext }) so runner.ts and console.ts no longer import any platform-specific module.
  • Construct the Node impl once in runInPool.ts; construct the Browser impl per test file in @rstest/browser/client/entry.ts.

User Impact

Removes the Critical dependency warning when @rstest/core/browser-runtime is bundled by a downstream consumer (reproducible via examples/browser-react).

@rstest/browser/client/entry.ts          packages/core/.../runInPool.ts
        │                                          │
        ▼                                          ▼
createBrowserTaskContext()              createNodeTaskContext()
        │                                          │
        └──────────── { taskContext } ─────────────┘
                              │
                              ▼
              createRstestRuntime(workerState, { taskContext })
                              │
                              ▼
                       TestRunner / console
                   (no platform-specific import)

Test plan

  • pnpm run lint — pass
  • pnpm run typecheck — pass
  • pnpm run build — pass
  • pnpm run test — 370/370 pass
  • examples/browser-react pnpm test — 6/6 pass, zero Critical dependency warnings (previously emitted 3 times per run)
  • silent reporter e2e — 6/6 pass (incl. concurrent attribution)
  • browser-mode console e2e — 5/5 pass (incl. silent=passed-only + disableConsoleIntercept combinations)
  • Full e2e — 605/607 pass; 2 pre-existing flakes (build/index.test.ts > should write output to customized distPath.root and browser-mode/snapshot.test.ts > should create snapshot files on first run) that pass in isolation and are unrelated to this change

…bundle

The previously-shared `taskContext` module used `await import(asyncHooksSpecifier)`
to lazily load `node:async_hooks` with a `/* webpackIgnore: true */` magic
comment. The variable specifier defeats Rspack's static analysis, so the
comment is silently ignored and the dependency lands in the browser-runtime
bundle, producing a `Critical dependency: the request of a dependency is
an expression` warning whenever a downstream consumer rebundles
`@rstest/core/browser-runtime`.

Split the module into:
  - taskContext.ts            — TaskContext interface only
  - taskContext.node.ts       — createNodeTaskContext() with static
                                `import { AsyncLocalStorage } from 'node:async_hooks'`
  - taskContext.browser.ts    — createBrowserTaskContext() with closure
                                fallback only

The instance is injected via createRstestRuntime(workerState, { taskContext })
so runner.ts and console.ts no longer import any platform-specific module.
Node side constructs the Node impl in runInPool.ts; browser entry constructs
the Browser impl per test file.
@fi3ework fi3ework requested a review from 9aoy May 12, 2026 08:17
@fi3ework fi3ework enabled auto-merge (squash) May 12, 2026 08:23
@github-actions

Copy link
Copy Markdown

Rsdoctor Bundle Diff Analysis

Found 12 projects in monorepo, 2 projects with changes.

📊 Quick Summary
Project Total Size Change
adapter-rsbuild 3.6 KB 0
adapter-rslib 24.6 KB 0
adapter-rspack 7.7 KB 0
browser 2.0 MB 0
browser-react 3.7 KB 0
browser-ui 803.5 KB 0
coverage-istanbul 9.6 KB 0
core/browser 970.0 KB -276.0 B (-0.0%)
core/loaders 869.0 B 0
core/main 1.6 MB -384.0 B (-0.0%)
vscode/extension 58.9 MB 0
vscode/worker 14.4 KB 0
📋 Detailed Reports (Click to expand)

📁 core/browser

Path: packages/core/.rsdoctor/browser/rsdoctor-data.json

📌 Baseline Commit: 9a875bdc95 | PR: #1241

Metric Current Baseline Change
📊 Total Size 970.0 KB 970.2 KB -276.0 B (-0.0%)
📄 JavaScript 961.8 KB 962.1 KB -276.0 B (-0.0%)
🎨 CSS 0 B 0 B 0
🌐 HTML 0 B 0 B 0
📁 Other Assets 8.1 KB 8.1 KB 0

📦 Download Diff Report: core/browser Bundle Diff

📁 core/main

Path: packages/core/.rsdoctor/main/rsdoctor-data.json

📌 Baseline Commit: 9a875bdc95 | PR: #1241

Metric Current Baseline Change
📊 Total Size 1.6 MB 1.6 MB -384.0 B (-0.0%)
📄 JavaScript 1.5 MB 1.5 MB -384.0 B (-0.0%)
🎨 CSS 0 B 0 B 0
🌐 HTML 0 B 0 B 0
📁 Other Assets 79.2 KB 79.2 KB 0

📦 Download Diff Report: core/main Bundle Diff

Generated by Rsdoctor GitHub Action

fi3ework added a commit that referenced this pull request May 12, 2026
Browser-mode e2e tests run rstest as a subprocess via `runBrowserCli` &
siblings, so any Rsbuild/Rspack build warning or Node deprecation lands
in `cli.stdout`/`cli.stderr` and is otherwise silently swallowed by the
parent test runner.

Decorate `expectExecSuccess` returned by the three browser-mode helpers
to additionally scan the captured CLI output for framework warning
markers (`Build warning:`, `Critical dependency:`, `DeprecationWarning:`,
`MODULE_TYPELESS_PACKAGE_JSON`). Any hit fails the test with the
offending lines included in the message.

This turns regressions like an `await import(<var>)` dynamic specifier
losing its `webpackIgnore` magic comment into explicit, debuggable test
failures instead of invisible noise.

Refs: #1244
@fi3ework fi3ework merged commit 5b1b1a2 into main May 12, 2026
22 checks passed
@fi3ework fi3ework deleted the fix/task-context-browser-bundle branch May 12, 2026 09:01
fi3ework added a commit that referenced this pull request May 12, 2026
Browser-mode e2e tests run rstest as a subprocess via `runBrowserCli` &
siblings, so any Rsbuild/Rspack build warning or Node deprecation lands
in `cli.stdout`/`cli.stderr` and is otherwise silently swallowed by the
parent test runner.

Decorate `expectExecSuccess` returned by the three browser-mode helpers
to additionally scan the captured CLI output for framework warning
markers (`Build warning:`, `Critical dependency:`, `DeprecationWarning:`,
`MODULE_TYPELESS_PACKAGE_JSON`). Any hit fails the test with the
offending lines included in the message.

This turns regressions like an `await import(<var>)` dynamic specifier
losing its `webpackIgnore` magic comment into explicit, debuggable test
failures instead of invisible noise.

Refs: #1244
fi3ework added a commit that referenced this pull request May 12, 2026
Browser-mode e2e tests run rstest as a subprocess via `runBrowserCli` &
siblings, so any Rsbuild/Rspack build warning or Node deprecation lands
in `cli.stdout`/`cli.stderr` and is otherwise silently swallowed by the
parent test runner.

Decorate `expectExecSuccess` returned by the three browser-mode helpers
to additionally scan the captured CLI output for framework warning
markers (`Build warning:`, `Critical dependency:`, `DeprecationWarning:`,
`MODULE_TYPELESS_PACKAGE_JSON`). Any hit fails the test with the
offending lines included in the message.

This turns regressions like an `await import(<var>)` dynamic specifier
losing its `webpackIgnore` magic comment into explicit, debuggable test
failures instead of invisible noise.

Refs: #1244
@9aoy 9aoy mentioned this pull request May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants