Skip to content

bun test --isolate: opt-in global reuse fast path - #36871

Open
robobun wants to merge 11 commits into
mainfrom
farm/490b3121/isolate-fast-reset
Open

bun test --isolate: opt-in global reuse fast path#36871
robobun wants to merge 11 commits into
mainfrom
farm/490b3121/isolate-fast-reset

Conversation

@robobun

@robobun robobun commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

What

Adds an experimental opt-in fast path for bun test --isolate / --parallel: when a test file doesn't mutate the global environment, reuse the same JSGlobalObject for the next file (scrubbing leaked own properties and dropping only project-path module records) instead of creating a fresh one. node_modules and builtin module records survive, so their linked CodeBlocks and JIT'd code carry over.

Gated on BUN_FEATURE_FLAG_EXPERIMENTAL_ISOLATION_GLOBAL_REUSE=1; off by default.

The always-safe internal-module UnlinkedFunctionExecutable cache is split out to #36873.

bench/test/app (cd bench/test && bun install && bun app/setup.ts 2000 20 && cd app), 16-core Linux release, with the flag set:

before after
bun test --isolate tests 88.2s wall / 152s user 18.9s wall / 31s user
bun test --parallel tests 15.2s wall / 172s user 3.2s wall / 32s user

How

After --preload runs on a fresh global, Zig__GlobalObject__captureTestIsolationBaseline reifies every static hash-table global and snapshots globalThis's own-property slot values + attributes (as Strong<Unknown>), the lexical/var symbol-table sizes, the module-override / prepareStackTrace flags, and the set of module keys the preload chain loaded.

Before the next file, Zig__GlobalObject__tryResetForTestIsolation checks:

  • no prototype watchpoint fired (isHavingABadTime, {object,array,string}PrototypeChainIsSane, {array,map,set}IteratorProtocol)
  • globalLexicalEnvironment / var symbol table sizes unchanged
  • Module.wrapper / _resolveFilename / runMain / Error.prepareStackTrace match the baseline snapshot
  • (after first restoring any jest.spyOn targets) every baseline own property's slot value and attributes unchanged

If all of that holds, it deletes any extra own properties the file leaked (falling back to swap if a delete fails), drops the preload chain + project-path ESM/CJS registry entries, clears nextTickQueue / jest-mock active spies / event listeners / Bun.plugin state / overridenDateNow / process listeners+cached-cwd+uncaughtExceptionCaptureCallback, and reuses the global. Any check failing falls back to the full createForTestIsolation swap and re-captures the baseline on the new global.

The existing Rust-side per-file cleanup (sockets, timers, watchers, subprocesses, cwd restore) runs in both cases.

Known limitations (why this is experimental)

Under the fast path, things the pristine check does not catch leak into the next file:

  • node_modules / node:* / bun:* module-level state loaded by the test file (e.g. axios.defaults.baseURL = ..., z.setErrorMap(...)). The preload chain itself re-evaluates every file.
  • mutations to a built-in object's members without replacing the property itself (Math.random = fn, process.env.X = y, process.stdin, Bun.inspect = ...)
  • dual-package identity: if a node_modules package loaded by --preload (e.g. react via @testing-library/react cleanup) is also imported by a test-file-loaded node_modules package (e.g. @tanstack/react-query), the preload copy is evicted and re-evaluated while the test-loaded importer stays linked to the original, so the next file sees two instances (Invalid hook call / instanceof / context-provider mismatches).

Project-path modules still re-evaluate fresh, and a file that replaces a global (globalThis.fetch = mock) or fires a prototype watchpoint is detected and falls back to the full swap.

Tests

6 new cases in test/cli/test/isolation.test.ts via a testIsolationResetStats hook on bun:internal-for-testing: off by default; reuses when clean (string- and symbol-keyed leaks scrubbed, jest.fn() / process.nextTick work, node_modules record survives two hops); falls back on built-in overwrite; falls back on prototype watchpoint; falls back on non-configurable leak; node_modules --preload re-registers hooks, jest.spyOn / jest.setSystemTime / process.on are restored and don't accumulate. The existing leaked global is not visible, module state is not shared, preload re-run, chdir, fake-timer and socket/watch cleanup cases still pass (they take the default full-swap path).

On import-heavy suites the per-file --isolate cost is dominated by
re-linking and re-evaluating every module in a fresh JSGlobalObject, and
re-tiering the same hot functions per global. Profiling bench/test/app
(2000 files importing zod + date-fns + lodash) showed parsing is already
negligible (SourceProvider/CodeCache sharing works); the cost is the
module graph rebuilding.

When a file leaves globalThis in its post-preload shape (no built-in
own property overwritten, no prototype watchpoint fired, no top-level
lexical bindings added, Module.wrapper/prepareStackTrace untouched) we
now scrub any extra own properties it leaked, drop only project-path
ESM/CJS registry entries, and reuse the same global. node_modules and
builtin module records survive, so their linked CodeBlocks and JIT'd
code carry over to the next file. Anything that fails the check falls
back to the existing createForTestIsolation swap.

Also cache each internal JS module's UnlinkedFunctionExecutable per-VM
so a fresh global re-link()s instead of re-parsing; createBuiltinExecutable
bypasses CodeCache so this was paying a full parse + bytecodegen per
global before.

bench/test/app, 2000 files, 16-core linux release:

  --isolate (serial)   88.2s / 152s user  ->  18.9s / 31s user
  --parallel           15.2s / 172s user  ->   3.2s / 32s user

BUN_FEATURE_FLAG_DISABLE_ISOLATION_GLOBAL_REUSE=1 forces the full swap.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Test isolation now supports experimental global reuse. The VM captures baseline state, resets reusable globals, and falls back to full swaps when validation fails. CLI controls, statistics bindings, and isolation tests cover the behavior.

Test isolation global reuse

Layer / File(s) Summary
Isolation controls and bindings
src/bun_core/env_var.rs, src/jsc/VirtualMachine.rs, src/runtime/cli/..., src/jsc/JSGlobalObject.rs, src/jsc/bindings/BunClientData.h
The feature flag controls global reuse. VM state tracks baseline capture and reuse. Rust and C++ bindings expose baseline operations and per-VM baseline storage.
Baseline capture and global reset
src/jsc/bindings/ZigGlobalObject.cpp, src/jsc/bindings/BunProcess.h
The global object snapshots properties and module state, validates reset conditions, removes leaked state, clears cached CWD, and records reuse or swap results.
VM isolation orchestration
src/jsc/VirtualMachine.rs
The VM captures a baseline once and attempts reuse during isolated test entry-point reloads. Failed resets create a new global.
Statistics binding and isolation coverage
src/jsc/bindings/InternalForTesting.*, src/js/internal-for-testing.ts, test/cli/test/isolation.test.ts
Testing bindings expose reuse and swap counters. Tests cover default swaps, reusable cleanup, module behavior, prototype and property mutations, spies, and preloads.

Possibly related issues

  • oven-sh/bun#36815 — Concerns test isolation global and project-module cleanup addressed by this implementation.
  • oven-sh/bun#35301 — Concerns test isolation state reset, mock cleanup, and module-cache handling addressed by this implementation.

Possibly related PRs

  • oven-sh/bun#36810 — Extends the same experimental global-reuse implementation across VM state, bindings, CLI controls, and isolation tests.

Suggested reviewers: cirospaciari, jarred-sumner, sosukesuzuki

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the experimental opt-in global reuse fast path for Bun test isolation.
Description check ✅ Passed The description explains the change, implementation, limitations, benchmarks, and verification results in sufficient detail.

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the claude label Aug 4, 2026
Comment thread src/jsc/VirtualMachine.rs Outdated
Comment thread src/jsc/VirtualMachine.rs Outdated
Comment thread src/jsc/bindings/BunClientData.h Outdated
Comment thread src/jsc/bindings/BunClientData.h Outdated
Comment thread src/jsc/bindings/InternalModuleRegistry.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/VirtualMachine.rs Outdated
Comment thread src/jsc/bindings/InternalModuleRegistry.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

Split the unlinked executable code out.

And then let's make the isolation more granular. What about process.stdin. What about reassigning to the LazyProperty callbacks on Bun? What about stdin, stdout, stderr. What about mocks.

And this definitely can't be a default. It has to be some other setting.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/jsc/bindings/ZigGlobalObject.cpp`:
- Around line 807-810: Update the deletion loop in the global-object cleanup
path to inspect the boolean result of JSC::JSCell::deleteProperty for each id;
when any deletion fails, immediately return swap() instead of reporting
successful cleanup, while preserving the existing loop for successful deletions.
- Around line 702-706: Update the Entry baseline storage in the ownProperties
map to use JSC::Strong<JSC::Unknown> instead of JSC::EncodedJSValue, ensuring
baseline JavaScript values remain GC-rooted. Adjust the baseline capture and
reset comparison logic associated with ownProperties to compare the Strong’s
current value while preserving the unchanged-value behavior.

In `@test/cli/test/isolation.test.ts`:
- Around line 506-518: Add a test case alongside the existing built-in and
Array.prototype mutation cases that assigns a symbol-keyed own property on
globalThis, then verifies the next isolated file cannot observe it and that
stats?.swap is at least 1. Include the relevant symbol-keyed mutation variants
required by the fixture matrix while preserving the existing successful exit and
pass-count assertions.
- Around line 521-529: Update the reuseFixtures scenario in the
“BUN_FEATURE_FLAG_DISABLE_ISOLATION_GLOBAL_REUSE=1” test so b.test.ts mutates an
observable package or global value and c.test.ts asserts that value is absent.
Preserve the existing a.test.ts-to-b.test.ts isolation assertion while adding
coverage for the b.test.ts-to-c.test.ts transition, verifying both forced full
swaps.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 13b2a422-c0c4-4a68-848d-71e07f12d4e4

📥 Commits

Reviewing files that changed from the base of the PR and between 87e168f and 8cb1b37.

📒 Files selected for processing (13)
  • src/bun_core/env_var.rs
  • src/js/internal-for-testing.ts
  • src/jsc/JSGlobalObject.rs
  • src/jsc/VirtualMachine.rs
  • src/jsc/bindings/BunClientData.h
  • src/jsc/bindings/BunProcess.h
  • src/jsc/bindings/InternalForTesting.cpp
  • src/jsc/bindings/InternalForTesting.h
  • src/jsc/bindings/InternalModuleRegistry.cpp
  • src/jsc/bindings/ZigGlobalObject.cpp
  • src/runtime/cli/test/parallel/runner.rs
  • src/runtime/cli/test_command.rs
  • test/cli/test/isolation.test.ts

Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread test/cli/test/isolation.test.ts
Comment thread test/cli/test/isolation.test.ts Outdated
@robobun

robobun commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Splitting the UnlinkedFunctionExecutable cache into its own PR now.

For this PR I'll flip the reuse path to opt-in (new setting, off by default) and add the deleteProperty result check + GC-root the baseline values. The granularity gaps (process.stdin/out/err, Bun.* lazy properties, mock restoration) I'll list explicitly as known limitations of the opt-in mode; detecting mutations to those would need per-object structure snapshots which I can add as a follow-up if the opt-in shape looks right.

Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/InternalModuleRegistry.cpp Outdated
Comment thread src/jsc/VirtualMachine.rs Outdated
@robobun

robobun commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 6:10 AM PT - Aug 4th, 2026

@robobun, your commit 5aaa813f7e45c15aa3aaef6b85c5d99844a27bd9 passed in Build #88801! 🎉


🧪   To try this PR locally:

bunx bun-pr 36871

That installs a local version of the PR into your bun-36871 executable, so you can run:

bun-36871 --bun

…opes

Per review: the reuse path changes --isolate semantics (node_modules
module state persists; Bun.* / process.* mutations not detected), so it
cannot be a default. Gate on BUN_FEATURE_FLAG_EXPERIMENTAL_ISOLATION_GLOBAL_REUSE=1.

Also:
- mockModule = {} zeroed every LazyProperty m_pointer, losing the
  initLater callback tag, so jest.fn() after a reuse passed a null
  Structure* into allocateCell. Clear only activeSpies/activeMocks.
- Wrap deleteProperty/JSMapIterator/remove/reifyAllStaticProperties in a
  TopExceptionScope (CI x64-asan tripped the unchecked-exception
  validator at JSOrderedHashTableHelper removeImpl).
- swap() if deleteProperty returns false (non-configurable leak).
- Skip baseline capture entirely when reuse is off.
- Drop the internal-module executable cache (split out to #36873).
@robobun robobun changed the title bun test --isolate: reuse the global when a file leaves it pristine bun test --isolate: opt-in global reuse fast path Aug 4, 2026
@robobun

robobun commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Diff is ready for review at 5aaa813. CI build 88801 has 9 failures, all classified [flaky] (password leak threshold, install-patch, watch-many-dirs, shell leak, spawn-maxbuf, v8-heap-snapshot, node-sqlite parallel batch, napi node-gyp), none touching this diff. test/cli/test/isolation.test.ts passed on every lane.

The gate check separately keeps hitting "BUILD FAILED (no junit output)" (stray untracked V8*.cpp / JSCompressionStream*.cpp files in the gate container globbed into ninja). Locally: bun bd + bun run build:release clean, 27/27 isolation tests pass, fail-before on origin/main verified.

Whole reuse path is gated on BUN_FEATURE_FLAG_EXPERIMENTAL_ISOLATION_GLOBAL_REUSE=1; the default --isolate code path is unchanged.

Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
…eload chain

- Entry::value is now Strong<Unknown> (raw EncodedJSValue in malloc'd
  memory is an ABA hazard once a test overwrites a baseline global).
- JSMock__resetSpies instead of activeSpies.clear() so an unrestored
  jest.spyOn target is restored rather than having its recovery path
  dropped.
- Remove m_nextTickQueue.clear(): the reified process.nextTick closure
  captures the queue cell, so nulling the global's field left every
  drain site skipping and nextTick callbacks silently dropped.
- Record module-map and require-map keys at baseline (i.e. everything
  --preload loaded) and evict them on reset regardless of path, so a
  node_modules preload (or its transitive CJS deps) re-evaluates and
  re-registers hooks that reset_hook_scope_for_test_isolation dropped.
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/jsc/bindings/ZigGlobalObject.cpp`:
- Around line 896-897: Update the cleanup flow around JSMock__resetSpies so
that, when spy restoration leaves an exception, the exception is cleared and
swap() is returned before reporting successful reuse. Preserve the normal
successful-reset path while preventing the next isolated file from observing
partially restored spies.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1d99ced2-bf0c-4cd6-bacf-2665ae0b7ede

📥 Commits

Reviewing files that changed from the base of the PR and between 8cb1b37 and e2af3c1.

📒 Files selected for processing (7)
  • src/bun_core/env_var.rs
  • src/jsc/VirtualMachine.rs
  • src/jsc/bindings/BunClientData.h
  • src/jsc/bindings/ZigGlobalObject.cpp
  • src/runtime/cli/test/parallel/runner.rs
  • src/runtime/cli/test_command.rs
  • test/cli/test/isolation.test.ts
💤 Files with no reviewable changes (1)
  • src/jsc/bindings/BunClientData.h

Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
Comment thread src/jsc/VirtualMachine.rs
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
…e check; re-capture baseline after reuse

- Move JSMock__resetSpies before the own-property compare so
  spyOn(globalThis, builtin) is reverted to the baseline value (reuse
  succeeds) and the scrub can't be undone by clearSpy restoring a key it
  just deleted.
- Clear baseline_captured on the reuse return: the preload chain
  re-evaluates on the reused global and may assign fresh object
  identities to globalThis; without a re-capture the next pristine check
  compares against stale Strong<> refs and swap-alternates.
- Reset overridenDateNow (jest.setSystemTime without useFakeTimers
  leaves it set) and process EventEmitter listeners (preload re-eval
  would append one more per file) alongside clearCachedCwd.
Comment thread src/jsc/VirtualMachine.rs
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
…ptureCallback

Re-capturing the baseline on a reused global was snapshotting the entire
moduleMap into preloadModuleKeys, which at that point also holds the
node_modules records the previous reset deliberately kept, so the next
reset evicted them (alternating hit/miss). The preload graph is stable
across reuses; keep the first capture's snapshot.

Also clear m_uncaughtExceptionCaptureCallback / m_reportOnUncaughtException
in the Process reset block (same native-field class as cachedCwd and
overridenDateNow already handled there).
Comment thread src/jsc/bindings/ZigGlobalObject.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/cli/test/isolation.test.ts`:
- Around line 503-508: In test/cli/test/isolation.test.ts, assert the collected
exitCode is zero after the existing output and state assertions at lines
503-508, specifically after pkgSlotC, and at lines 606-609, after the
reset-statistics assertion. Update both subprocess test sites so successful
output and state checks also require clean child termination.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d553c147-a27f-4a74-b408-82ac860b5d9f

📥 Commits

Reviewing files that changed from the base of the PR and between e2af3c1 and 43297be.

📒 Files selected for processing (3)
  • src/jsc/VirtualMachine.rs
  • src/jsc/bindings/ZigGlobalObject.cpp
  • test/cli/test/isolation.test.ts

Comment thread test/cli/test/isolation.test.ts
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
…at baseline

- onLoadPlugins/onResolvePlugins were never cleared, so a preload that
  calls Bun.plugin(...) appended one more filter/callback pair per
  reused file (unbounded Strong<> accumulation, O(N) regex matches per
  import).
- The hasOverriddenModule* / prepareStackTrace checks compared against
  zero, so a preload that sets Error.prepareStackTrace or patches
  Module._resolveFilename (source-map-support, tsconfig-paths) swapped
  on every file. Snapshot them at baseline and compare to the snapshot.
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp
Comment thread src/jsc/bindings/ZigGlobalObject.cpp Outdated
… reset

- swap() now clears ownProperties/prepareStackTraceValue so the outgoing
  global isn't pinned by ~100+ Strong<> handles through the idle window
  before the next capture.
- BunPlugin::OnLoad has a user-declared dtor, so = {} selects the
  implicit copy-assign which overwrites the raw virtualModules pointer
  without deleting it (leaking the map + every Strong<JSObject> mock
  callback per reused file).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/jsc/bindings/ZigGlobalObject.cpp (1)

880-889: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Replace isProjectPath heuristics with URL and path parsing to prevent test-isolation cache mismatches.

The isProjectPath function classifies module cache keys using substring matching and character position checks. When a cache key is scheme-qualified (e.g., file:///path/to/module.js) or non-canonical, it fails to match the patterns and is incorrectly retained. This breaks test isolation when project modules are not removed.

Parse the key with WTF::URL if it contains a scheme. For path-only keys, use the existing path normalization and node_modules detection. Ensure both ESM (moduleMap) and CommonJS (requireMap) keys are classified consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/jsc/bindings/ZigGlobalObject.cpp` around lines 880 - 889, Replace the
heuristic logic in isProjectPath with URL parsing for scheme-qualified keys and
the existing path normalization plus node_modules detection for path-only keys.
Ensure canonical and non-canonical project paths, including file URLs, are
recognized consistently, and apply the same classification when filtering both
moduleMap and requireMap entries.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/jsc/bindings/ZigGlobalObject.cpp`:
- Around line 880-889: Replace the heuristic logic in isProjectPath with URL
parsing for scheme-qualified keys and the existing path normalization plus
node_modules detection for path-only keys. Ensure canonical and non-canonical
project paths, including file URLs, are recognized consistently, and apply the
same classification when filtering both moduleMap and requireMap entries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0723b25e-d34c-4f20-b904-2ea80270db64

📥 Commits

Reviewing files that changed from the base of the PR and between 43297be and 5aaa813.

📒 Files selected for processing (1)
  • src/jsc/bindings/ZigGlobalObject.cpp

Comment thread test/cli/test/isolation.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants