Skip to content

Conversation

@robobun
Copy link
Collaborator

@robobun robobun commented Jan 21, 2026

Summary

  • Fixes process.env.hasOwnProperty() throwing "TypeError: environment.hasOwnProperty is not a function" on Windows
  • The Windows process.env Proxy now correctly returns inherited Object.prototype methods when no env var exists with that name
  • Methods are bound to the proxy so they work correctly (e.g., hasOwnProperty checks the proxy, not the underlying object)

Fixes #26315

Test plan

  • Added regression test at test/regression/issue/26315.test.ts
  • Test verifies hasOwnProperty, propertyIsEnumerable, toString, valueOf, and isPrototypeOf work correctly
  • Test verifies env vars with names matching Object.prototype methods are still accessible via uppercase

🤖 Generated with Claude Code

@robobun
Copy link
Collaborator Author

robobun commented Jan 21, 2026

Updated 8:52 PM PT - Jan 20th, 2026

❌ Your commit a9effc70 has 2 failures in Build #35469 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 26316

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

bun-26316 --bun

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 21, 2026

Walkthrough

Windows-specific process.env proxy get handler now checks Object.prototype members for string keys (returning bound callables or properties) before falling back to case-insensitive env lookup; a regression test file was added to validate method access and name-conflict behavior.

Changes

Cohort / File(s) Summary
Process Object Internals
src/js/builtins/ProcessObjectInternals.ts
Proxy get(target, p, receiver) switched to three-argument form and uses a cached Object.prototype reference. For string keys, if Object.prototype[p] exists return it (wrap callable members to call with the proxy as this via the receiver); otherwise perform case-insensitive env lookup with internalEnv[p.toUpperCase()]. Non-string keys return undefined. Surrounding set/has/delete/define semantics preserved.
Regression Tests
test/regression/issue/26315.test.ts
Added tests asserting process.env exposes Object.prototype methods (hasOwnProperty, propertyIsEnumerable, toString, valueOf, isPrototypeOf) and verifies behavior when environment variables conflict with prototype method names (including cleanup).
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main fix: handling Object.prototype methods on Windows process.env.
Description check ✅ Passed The description covers the key objectives, including the fix details, test plan with specific test file location, and references the linked issue #26315.
Linked Issues check ✅ Passed The code changes directly address issue #26315 by fixing the Windows process.env proxy to return Object.prototype methods and adding comprehensive regression tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the Windows process.env issue: the proxy implementation in ProcessObjectInternals.ts and regression tests in 26315.test.ts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/js/builtins/ProcessObjectInternals.ts`:
- Around line 391-407: The proxy get handler currently checks internalEnv (via
upperKey) before checking Object.prototype methods, causing prototype methods
like hasOwnProperty to be shadowed by env strings; update the get handler in
ProcessObjectInternals (function get, symbols: p, upperKey, internalEnv,
objectProto, receiver) to first check if p exists on objectProto and, if so,
return the bound method or property, and only if not present fall back to
checking internalEnv[upperKey] so env vars remain accessible via uppercase but
Object.prototype methods remain callable.
- Around line 389-405: Replace uses of the public globals in the Proxy get
handler: instead of using Object.prototype (objectProto) and typeof checks,
reference the intrinsic $Object to access its prototype and use the $isCallable
helper for callable checks. Concretely, update the variable currently assigned
from Object.prototype to use $Object.prototype, and change the typeof method ===
"function" guard to use $isCallable(method); ensure you still bind the method to
receiver when callable and keep the same branch logic in the get handler for
internalEnv lookup and fallback to prototype methods.

In `@test/regression/issue/26315.test.ts`:
- Around line 7-26: Tests assume PATH exists; change both tests (the
"process.env.hasOwnProperty works" and "process.env.propertyIsEnumerable works")
to create a temporary env var (e.g., set process.env.__TEST_TMP_VAR__ = "1"),
assert hasOwnProperty/propertyIsEnumerable against that key, then delete the key
(or restore prior value) in cleanup to avoid leaking state; reference the uses
of process.env.hasOwnProperty and process.env.propertyIsEnumerable in the two
test blocks when making the change.

@robobun robobun force-pushed the claude/fix-windows-process-env-hasOwnProperty branch from 01a8af5 to 655c7d1 Compare January 21, 2026 03:59
@robobun
Copy link
Collaborator Author

robobun commented Jan 21, 2026

Addressed all review comments:

  1. Use $Object.prototype and $isCallable intrinsics - ✅ Changed Object.prototype to $Object.prototype and typeof method === "function" to $isCallable(method)

  2. Check prototype methods before env vars - ✅ Reordered the logic to check Object.prototype first, preventing env vars from shadowing prototype methods. This ensures methods like hasOwnProperty remain callable even if someone sets a HASOWNPROPERTY env var.

  3. Use temp env var in tests instead of PATH - ✅ Updated both test cases to create temporary env vars (__TEST_HAS_OWN_PROPERTY_26315__ and __TEST_PROP_IS_ENUM_26315__) with proper cleanup in finally blocks.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/js/builtins/ProcessObjectInternals.ts`:
- Around line 389-407: The current code uses method.bind(receiver) which can be
hijacked if Function.prototype.bind is mutated; update the return path in the
get trap so that instead of calling method.bind(receiver) you return a protected
wrapper that invokes the original method with the receiver via the intrinsic
call/apply helpers (e.g. use the existing $call or $apply primitive to invoke
method with receiver and forwarded arguments). Change the branch that checks
objectProto and $isCallable (the code referencing objectProto, $isCallable, and
method.bind(receiver)) to return a small wrapper that forwards args to
$call(method, receiver, ...args) (or the project’s equivalent protected
Function.prototype.call wrapper) to avoid relying on the untrusted bind
implementation.

On Windows, process.env is wrapped in a Proxy for case-insensitive access.
The get trap previously converted all property names to uppercase and looked
them up in the env map, which meant inherited methods like hasOwnProperty
returned undefined (or threw an error when called).

This fix checks if the property is an inherited Object.prototype method
first (before looking up env vars), and returns a wrapper function that
invokes the method with the proxy as `this` so it works correctly.

Uses $Object.prototype, $isCallable, and $call intrinsics per code review
feedback to avoid relying on potentially mutated prototypes.

Fixes #26315

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@robobun robobun force-pushed the claude/fix-windows-process-env-hasOwnProperty branch from 655c7d1 to a9effc7 Compare January 21, 2026 04:09
@robobun
Copy link
Collaborator Author

robobun commented Jan 21, 2026

Updated to address the latest review comment:

  1. Use protected $call instead of bind - ✅ Replaced method.bind(receiver) with a wrapper function that uses method.$call(receiver, ...args) to avoid relying on potentially mutated Function.prototype.bind.

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.

TypeError: environment.hasOwnProperty is not a function

2 participants