Skip to content

process: reject accessor/partial descriptors in Object.defineProperty(process.env, ...) - #34727

Open
robobun wants to merge 6 commits into
mainfrom
claude/farm/747ec400/process-env-defineproperty
Open

process: reject accessor/partial descriptors in Object.defineProperty(process.env, ...)#34727
robobun wants to merge 6 commits into
mainfrom
claude/farm/747ec400/process-env-defineproperty

Conversation

@robobun

@robobun robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Node.js throws ERR_INVALID_OBJECT_DEFINE_PROPERTY when Object.defineProperty is called on process.env with anything other than a fully-specified {value, writable: true, enumerable: true, configurable: true} data descriptor (see node_env_var.cc EnvDefiner). An accessor descriptor can never be reflected into the real environment block, so Node rejects it outright.

Bun previously accepted such descriptors silently, leaving an env key whose value never reaches child processes.

const assert = require('assert');
assert.throws(
  () => Object.defineProperty(process.env, 'goo', { get() { return 'g'; }, set() {} }),
  { code: 'ERR_INVALID_OBJECT_DEFINE_PROPERTY', name: 'TypeError' },
);
// node v26: throws
// bun 1.4.0: Missing expected exception (TypeError)

How did you verify your code works?

  • test/js/node/process/process.test.js: new Object.defineProperty on process.env ... case covering accessor, partial, and false-attribute descriptors plus the valid form.
  • test/js/node/test/parallel/test-process-env-ignore-getter-setter.js: imported verbatim from Node.js, passes with exit 0.
  • test/js/node/worker_threads/worker_threads.test.ts: the existing SHARE_ENV accessor test is updated to assert the shared map now matches the regular map (both throw).

Implementation

  • JSEnvironmentVariableMap.cpp: added JSProcessEnvMap, a JSNonFinalObject subclass whose only method-table override is defineOwnProperty, which validates the descriptor via throwIfInvalidEnvDescriptor and delegates to Base on success. createEnvironmentVariablesMap now instantiates this class instead of a plain JSFinalObject.
  • JSSharedEnvMap::defineOwnProperty now runs the same validation first; the old store-shadowing branch (only reachable for accessors/partial descriptors) is dead and removed.
  • ProcessObjectInternals.ts (Windows proxy): the defineProperty trap validates before touching envMapList or calling SetEnvironmentVariableW, then writes the stringified value through the same path as set.

no test proof · iteration 1 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/node/process/process.test.js

…erty(process.env, ...)

Node.js's process.env EnvDefiner rejects any descriptor that is not a
fully-specified {value, writable: true, enumerable: true, configurable: true}
data descriptor with ERR_INVALID_OBJECT_DEFINE_PROPERTY, because a
getter/setter cannot be reflected into the real environment block. Bun
previously accepted such descriptors silently.

The regular process.env is now a thin JSNonFinalObject subclass whose only
override is defineOwnProperty to perform this validation; the Windows Proxy
trap and the SHARE_ENV worker map do the same check.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

process.env now enforces Node-compatible complete data descriptors, applies string coercion consistently, uses validating maps for workers and shared environments, supports structured cloning, and adds coverage for descriptor, worker, and inheritance behavior.

process.env descriptor enforcement

Layer / File(s) Summary
Descriptor validation and environment updates
src/jsc/bindings/JSEnvironmentVariableMap.cpp, src/js/builtins/ProcessObjectInternals.ts
Regular, shared, and Windows process.env implementations reject accessor or incomplete descriptors and accept fully specified string-valued data descriptors.
Regular and worker map construction
src/jsc/bindings/JSEnvironmentVariableMap.h, src/jsc/bindings/JSEnvironmentVariableMap.cpp, src/jsc/bindings/ZigGlobalObject.cpp
Regular and worker environments use the validating map type, with explicit exception checks during worker population.
Structured clone eligibility
src/jsc/bindings/JSEnvironmentVariableMap.h, src/jsc/bindings/JSEnvironmentVariableMap.cpp, src/jsc/bindings/webcore/SerializedScriptValue.cpp
Process environment map classes are recognized by structured-clone serialization and accepted as plain-object-compatible values.
Descriptor behavior coverage
test/js/node/process/process.test.js, test/js/node/test/parallel/test-process-env-ignore-getter-setter.js
Tests cover rejected descriptors, accepted complete descriptors, value coercion, structured cloning, and deletion.
Worker and shared environment coverage
test/js/node/test/parallel/test-worker-process-env.js, test/js/node/worker_threads/worker_threads.test.ts
Tests cover worker isolation and inheritance, child processes, supplied environment validation, and rejected shared-environment accessors.

Possibly related PRs

  • oven-sh/bun#34728: Updates related Windows process.env value coercion and synchronization in defineProperty handling.

Suggested reviewers: jarred-sumner, cirospaciari

🚥 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 and concisely summarizes the main change: rejecting invalid process.env property descriptors.
Description check ✅ Passed The description follows the template and includes both required sections with clear implementation and verification details.

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

@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 6:59 PM PT - Jul 19th, 2026

@robobun, your commit 22a0e9d has 1 failures in Build #75903 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 34727

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

bun-34727 --bun

@github-actions

Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. process/worker: env descriptor validation, worker execArgv policy table with per-worker --expose-gc (+3 tests, worker 74%→76%) #34654 - Also rejects partial property descriptors on process.env via a custom JSProcessEnvMap class with defineOwnProperty validation; process: reject accessor/partial descriptors in Object.defineProperty(process.env, ...) #34727 is a superset that additionally rejects accessor descriptors

🤖 Generated with Claude Code

Workers spawned with env: {...} build process.env via constructEmptyObject
in ZigGlobalObject.cpp, bypassing JSProcessEnvMap entirely. Route that path
through createEmptyProcessEnvMap so defineOwnProperty validation applies
there too. Adds Node's test-worker-process-env.js verbatim.

Co-authored-by: Ciro Spaciari <6379399+cirospaciari@users.noreply.github.com>
@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Overlaps with #34654, which I'd missed. That PR uses the same JSProcessEnvMap approach but deliberately keeps accessor and empty descriptors accepted to preserve the worker_threads.test.ts accessor test; this PR rejects them to match Node exactly, per the request that opened it.

#34654 also catches the snapshot-env worker path (new Worker(f, {env: {...}}) builds process.env via constructEmptyObject in ZigGlobalObject.cpp), which the first commit here missed. Pulled that fix plus Node's test-worker-process-env.js into 3a8672d with co-author credit. The Windows defineProperty trap ordering hazard #34654 flags is also fixed here.

Net difference vs #34654: accessor/empty/{attr: false} descriptors now throw too (the worker_threads.test.ts accessor test is updated to assert both maps throw), and the Windows Proxy trap validates before touching envMapList/SetEnvironmentVariableW.

@claude claude 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.

Additional findings (outside current diff — PR may have been updated during review):

  • 🔴 src/jsc/bindings/JSEnvironmentVariableMap.cpp:817-818 — There's a fourth process.env creation site this PR doesn't cover: ZigGlobalObject.cpp:565 builds a snapshot-env worker's process.env via JSC::constructEmptyObject(...) — a plain JSFinalObject with the stock defineOwnProperty — so Object.defineProperty(process.env, 'x', {get(){}}) inside new Worker(..., { env: {...} }) still succeeds silently. Node applies the same EnvDefiner interceptor to every worker regardless of the env option, so after this PR Bun diverges both from Node and from its own main-thread / SHARE_ENV behavior. The fix is a one-line swap of constructEmptyObject for JSProcessEnvMap::create at that site (or an explicit call-out that it's intentionally excluded).

    Extended reasoning...

    What the bug is

    This PR introduces JSProcessEnvMap (whose only method-table override is defineOwnProperty running throwIfInvalidEnvDescriptor) and wires it into three of the four process.env creation sites: createEnvironmentVariablesMap (main thread / default workers), JSSharedEnvMap::defineOwnProperty (SHARE_ENV workers), and the Windows windowsEnv Proxy trap. The fourth site — ZigGlobalObject.cpp:565 — is not touched:

    if (options.env.has_value()) {
        HashMap<String, String> map = *std::exchange(options.env, std::nullopt);
        ...
        auto env = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), ...);
        ...
        globalObject->m_processEnvObject.set(vm, globalObject, env);
    }

    constructEmptyObject returns a plain JSFinalObject whose method table has the default JSObject::defineOwnProperty, so throwIfInvalidEnvDescriptor is never reached for this worker's process.env.

    The code path that triggers it

    options.env is populated in JSWorker.cpp whenever the user passes an explicit env: {...} object to new Worker(...), and also (via the m_processEnvObject.isInitialized() branch) when no env option is given but the parent has already touched process.env — the parent's env is snapshotted into options.env. In both cases the branch above runs, m_processEnvObject.set() is called directly at line 572, and the lazy initLater that would have called createEnvironmentVariablesMap (and thus produced a JSProcessEnvMap) is bypassed. On Windows the windowsEnv Proxy is likewise bypassed here, so the new Proxy trap doesn't cover this path either.

    Why existing code doesn't prevent it

    The PR's updated worker_threads.test.ts only exercises env: SHARE_ENV; there is no test for env: {...} or the default-snapshot path, so this gap is invisible to the test suite.

    Impact

    After this PR, Bun's own process.env variants diverge from each other: the main thread and SHARE_ENV workers throw ERR_INVALID_OBJECT_DEFINE_PROPERTY on an accessor descriptor, while snapshot-env workers silently accept it. Node.js applies one env_proxy_template / EnvDefiner interceptor to every realm regardless of which KVStore (RealEnvStore vs MapKVStore) backs it, so Node rejects accessors uniformly. Per the repo's "fix the whole class in the same PR" rule this is exactly the kind of sibling site that should be swept in — it's the same fix, not scope creep.

    Step-by-step proof

    const { Worker } = require('worker_threads');
    new Worker(
      `try { Object.defineProperty(process.env, 'x', { get() {} }); console.log('accepted'); }
       catch (e) { console.log(e.code); }`,
      { eval: true, env: { A: '1' } },
    );
    1. new Worker(..., { env: { A: '1' } }) sets options.env to { A: '1' }.
    2. In the worker's global setup, options.env.has_value() is true → ZigGlobalObject.cpp:565 builds env via constructEmptyObject and stores it directly with m_processEnvObject.set(...).
    3. Inside the worker, process.env is that plain JSFinalObject. Object.defineProperty(process.env, 'x', { get(){} }) dispatches to JSObject::defineOwnProperty, which installs the accessor without complaint.
    4. Node v26 prints ERR_INVALID_OBJECT_DEFINE_PROPERTY; Bun after this PR prints accepted.

    Fix

    Swap the plain object for the new class at ZigGlobalObject.cpp:565 (and export JSProcessEnvMap from the .cpp or add a small factory alongside createSharedEnvironmentVariablesMap):

    auto* structure = Bun::JSProcessEnvMap::createStructure(vm, globalObject, globalObject->objectPrototype());
    auto* env = Bun::JSProcessEnvMap::create(vm, structure);

    Then extend the worker test to also probe { eval: true, env: { A: '1' } } with the same accessor-descriptor assertion.

@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Already addressed in 3a8672d (pushed before this review landed): ZigGlobalObject.cpp:565 now calls Bun::createEmptyProcessEnvMap(globalObject), and Node's test-worker-process-env.js is added verbatim to cover the env: {...} snapshot path.

… setup

putDirectMayBeIndex on a JSNonFinalObject dispatches index-like keys through
the method table's defineOwnProperty (canDoFastPutDirectIndex is false for
non-JSFinalObject), which declares a ThrowScope. initializeWorker runs before
topEntryFrame is set, so that scope's destructor leaves m_needExceptionCheck
set and the next ThrowScope asserts under validateExceptionChecks=1.

Wrap the population loop in a TopExceptionScope (whose destructor does not
re-simulate) and acknowledge each put.
Comment thread src/jsc/bindings/JSEnvironmentVariableMap.cpp
Node's EnvDefiner delegates to EnvSetter which coerces the value to a string.
The Windows Proxy trap and JSSharedEnvMap already stringify; without this the
regular POSIX map would store the raw value and diverge from both Windows and
Node.

@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/JSEnvironmentVariableMap.cpp`:
- Around line 394-449: Update JSProcessEnvMap::defineOwnProperty to coerce a
present descriptor value to a string before delegating to
Base::defineOwnProperty, while preserving the existing descriptor validation and
attributes. Ensure Object.defineProperty assignments to process.env store string
values for numeric and object inputs, and add regression coverage for both
cases.
🪄 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: 94e1aa64-9003-4825-94e1-d141d99b42f7

📥 Commits

Reviewing files that changed from the base of the PR and between 99fc2f8 and 7427948.

📒 Files selected for processing (8)
  • src/js/builtins/ProcessObjectInternals.ts
  • src/jsc/bindings/JSEnvironmentVariableMap.cpp
  • src/jsc/bindings/JSEnvironmentVariableMap.h
  • src/jsc/bindings/ZigGlobalObject.cpp
  • test/js/node/process/process.test.js
  • test/js/node/test/parallel/test-process-env-ignore-getter-setter.js
  • test/js/node/test/parallel/test-worker-process-env.js
  • test/js/node/worker_threads/worker_threads.test.ts

Comment thread src/jsc/bindings/JSEnvironmentVariableMap.cpp
Comment thread src/jsc/bindings/JSEnvironmentVariableMap.cpp
robobun added 2 commits July 20, 2026 00:20
SerializedScriptValue's ObjectStartState gate admits only JSFinalObject,
NapiPrototype, and ObjectPrototype. Switching process.env to JSProcessEnvMap
(a JSNonFinalObject with its own ClassInfo) made structuredClone(process.env),
postMessage(process.env), and workerData: process.env throw DataCloneError.

Expose isProcessEnvClassInfo() and admit both env map classes at the gate.
On Windows process.env is a Proxy and the structured-clone serializer rejects
Proxy objects. This is pre-existing behavior independent of JSProcessEnvMap;
the test only guards the POSIX JSFinalObject->JSNonFinalObject change.

@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 (2)
src/jsc/bindings/JSEnvironmentVariableMap.cpp (1)

421-432: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Preserve side effects for special environment variables.

Base::defineOwnProperty replaces existing custom accessors with a plain data property. For TZ, NODE_TLS_REJECT_UNAUTHORIZED, BUN_CONFIG_VERBOSE_FETCH, and proxy variables, this bypasses the corresponding timezone/TLS/verbose-fetch/native-environment updates and disables the special setter for later writes. Route accepted descriptors through the same side-effecting update path and preserve special accessor behavior where required.

🤖 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/JSEnvironmentVariableMap.cpp` around lines 421 - 432, Update
defineOwnProperty in JSEnvironmentVariableMap so accepted descriptors use the
existing side-effecting environment-variable update path instead of directly
calling Base::defineOwnProperty, preserving custom accessors for TZ,
NODE_TLS_REJECT_UNAUTHORIZED, BUN_CONFIG_VERBOSE_FETCH, and proxy variables.
Retain string coercion and descriptor validation, while ensuring later writes
continue invoking each variable’s special setter.
test/js/node/process/process.test.js (1)

221-258: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Make the process.env test hermetic and exception-safe.

The test assumes foo and goo are unset, and cleanup occurs only after assertions. Use unique keys and wrap all mutations in try/finally, restoring any prior values so failures cannot contaminate subsequent tests.

As per coding guidelines, tests must isolate process-global state and restore globals in finally blocks.

🤖 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 `@test/js/node/process/process.test.js` around lines 221 - 258, Make the
Object.defineProperty process.env test hermetic by generating unique keys
instead of using fixed “foo” and “goo” names, and capture each key’s prior
value/state. Wrap all process.env mutations and assertions in try/finally
blocks, restoring or deleting the keys in finally so cleanup occurs even when an
assertion fails; preserve the existing descriptor validation and string-coercion
coverage.

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/JSEnvironmentVariableMap.cpp`:
- Around line 421-432: Update defineOwnProperty in JSEnvironmentVariableMap so
accepted descriptors use the existing side-effecting environment-variable update
path instead of directly calling Base::defineOwnProperty, preserving custom
accessors for TZ, NODE_TLS_REJECT_UNAUTHORIZED, BUN_CONFIG_VERBOSE_FETCH, and
proxy variables. Retain string coercion and descriptor validation, while
ensuring later writes continue invoking each variable’s special setter.

In `@test/js/node/process/process.test.js`:
- Around line 221-258: Make the Object.defineProperty process.env test hermetic
by generating unique keys instead of using fixed “foo” and “goo” names, and
capture each key’s prior value/state. Wrap all process.env mutations and
assertions in try/finally blocks, restoring or deleting the keys in finally so
cleanup occurs even when an assertion fails; preserve the existing descriptor
validation and string-coercion coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 76c1f02d-954c-4151-afa3-20bdc55f170e

📥 Commits

Reviewing files that changed from the base of the PR and between 7427948 and 22a0e9d.

📒 Files selected for processing (4)
  • src/jsc/bindings/JSEnvironmentVariableMap.cpp
  • src/jsc/bindings/JSEnvironmentVariableMap.h
  • src/jsc/bindings/webcore/SerializedScriptValue.cpp
  • test/js/node/process/process.test.js

@robobun

robobun commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Re the two coderabbit findings on 22a0e9d:

Special-variable side effects (TZ, NODE_TLS_REJECT_UNAUTHORIZED, proxy vars): pre-existing, not introduced here. On main (before this PR), process.env is a plain JSFinalObject, so Object.defineProperty(process.env, 'TZ', {value: 'UTC', writable: true, enumerable: true, configurable: true}) already went through JSObject::defineOwnProperty and replaced the CustomAccessor with a data property without firing the timezone-cache reset:

$ bun-1.4.0 -e 'const b = Intl.DateTimeFormat().resolvedOptions().timeZone;
  Object.defineProperty(process.env, "TZ", {value:"America/Anchorage",writable:true,enumerable:true,configurable:true});
  console.log(b, "->", Intl.DateTimeFormat().resolvedOptions().timeZone)'
UTC -> UTC

Routing accepted descriptors through the side-effecting setters would be a behavior change layered on top of the validation this PR adds; leaving it for a follow-up to keep scope bounded.

Test hermeticity: the foo key is never set (every foo assertion expects a throw), and goo is deleted after each set. The existing process.env tests in the same file follow the same set-then-delete pattern without try/finally, and each CI lane runs test files in separate processes.

@robobun

robobun commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Build #75903 has no failures in the files this PR touches. Remaining reds are [flaky]-tagged (repl-close EPIPE, http-client/server leak GC timing, serve-protocols HTTP3, bun-jsc profile sampling, filter-workspace eliding, fs-promises FileHandle GC) plus test-net-connect-memleak.js which is [pre-existing] on main and already owned by another fix session. Ready for review.

@claude claude 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.

No new issues found — both earlier inline concerns (value stringification, structured-clone whitelist) are addressed. Deferring to human review: this changes process.env's underlying class from JSFinalObject to a custom JSNonFinalObject with a method-table override, touches the structured-clone serializer and worker-global setup, and overlaps with #34654 (one will need closing).

What was reviewed:

  • throwIfInvalidEnvDescriptor against Node's EnvDefiner cases (accessor, partial, {attr:false}, empty) — messages match verbatim.
  • JSProcessEnvMap subspace/structure setup (STATIC_ASSERT_ISO_SUBSPACE_SHARABLE, plainObjectSpace, no instance state) and that PropertyDescriptor(value, 0) from putDirectIndex passes the validator during snapshot-env worker population.
  • Windows defineProperty trap: validation now precedes envMapList/SetEnvironmentVariableW writes, and the old editWindowsEnvVar(k, internalEnv[k]) (which passed the old value) is fixed.
  • Symbol-key handling: Node also throws ERR_INVALID_OBJECT_DEFINE_PROPERTY on symbol keys, so no divergence there.
Extended reasoning...

Overview

The PR replaces process.env's backing object (a plain JSFinalObject) with a new JSProcessEnvMap : JSNonFinalObject whose only method-table override is defineOwnProperty, which validates descriptors to match Node's EnvDefiner (rejects accessors, partial descriptors, and any {writable|enumerable|configurable: false}). The same validator is wired into JSSharedEnvMap (SHARE_ENV), the Windows Proxy trap, and the snapshot-env worker path in ZigGlobalObject.cpp. Because the class change broke the exact-classInfo() whitelist in SerializedScriptValue.cpp, an isProcessEnvClassInfo() helper is added to that gate. Two Node parallel tests are imported verbatim, plus targeted coverage in process.test.js and an updated SHARE_ENV accessor test.

Security risks

None identified. This tightens validation (rejects more inputs than before) and does not expose new capability. The structured-clone whitelist addition admits objects that behave as plain string maps — the same content that was clonable before the class change.

Level of scrutiny

Moderate-to-high. Changing the underlying JSC class of process.env is the kind of change with non-local consequences: any code path that keys on JSFinalObject::info(), FinalObjectType, or inline-capacity fast paths may now take a different branch. Two such consequences already surfaced during review (structured-clone rejection; putDirectMayBeIndex dispatching through the method table's defineOwnProperty during worker-env population, requiring a top-level exception scope). Both are handled, but the pattern suggests a human should sanity-check for other FinalObject-keyed fast paths.

Other factors

  • PR overlap: #34654 implements a subset of this via the same JSProcessEnvMap approach; a maintainer needs to decide which lands.
  • Prior review: I left two inline findings (stringify in JSProcessEnvMap::defineOwnProperty; structured-clone whitelist), both resolved in 64c4b25 and 2d862d6.
  • CI: green on the touched files; remaining reds are tagged flaky/pre-existing.
  • Windows: the structuredClone(process.env) test is skipped there because process.env is a Proxy (pre-existing serializer limitation, noted in the test comment).

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.

1 participant