fix(node): make patchGlobalRequest idempotent - #255
Conversation
A second call to `patchGlobalRequest()` skipped re-assigning `globalThis.Request` (guarded by the `_srvx` marker) but still built and returned a brand-new `PatchedRequest` class, so `patchGlobalRequest() === globalThis.Request` was false on repeated calls. Return the already-installed global when it is already patched, so repeated calls are idempotent and return the exact class installed as `globalThis.Request`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthrough
ChangesGlobal Request patching
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/adapters/_node/request.ts (1)
323-328: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueUse optional chaining for safer global access.
If
globalThis.Requesthappens to be undefined (e.g., in environments without a native or polyfilledRequest), accessing._srvxdirectly will throw aTypeError. Using optional chaining prevents this and is also consistent with howR?._srvxis safely checked ingetNativeRequest().♻️ Proposed refactor
// Idempotent: if the global is already patched, return the installed class // so `patchGlobalRequest() === globalThis.Request` holds on repeated calls. - if ((globalThis.Request as any)._srvx) { + if ((globalThis.Request as any)?._srvx) { return globalThis.Request as unknown as typeof Request; }🤖 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/adapters/_node/request.ts` around lines 323 - 328, Update the idempotency check in patchGlobalRequest() to use optional chaining when reading the _srvx marker from globalThis.Request, so the check safely handles environments where Request is undefined while preserving the existing return behavior for an already patched class.
🤖 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.
Nitpick comments:
In `@src/adapters/_node/request.ts`:
- Around line 323-328: Update the idempotency check in patchGlobalRequest() to
use optional chaining when reading the _srvx marker from globalThis.Request, so
the check safely handles environments where Request is undefined while
preserving the existing return behavior for an already patched class.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 08274582-9a62-4101-9bd0-9b4d71c4f178
📒 Files selected for processing (2)
src/adapters/_node/request.tstest/node-request-formdata.test.ts
The idempotence regression test belonged in a global-Request patching suite, not in the form-data test file. Remove it so the PR is just the source fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Problem
patchGlobalRequest()is meant to install a srvxRequestsubclass asglobalThis.Requestsonew Request(req)works in Node.js. It is intended to be safe to call more than once, but a second call was not idempotent:globalThis.Requestis guarded by!(globalThis.Request as any)._srvx, so a second call correctly skips re-installing the global.PatchedRequestclass on every call.As a result,
patchGlobalRequest() === globalThis.Requestwasfalseon the second (and every subsequent) call — the returned class was a fresh subclass that was never installed as the global. Any caller relying on the return value being the actual installedRequest(e.g.instanceofchecks, or capturing the class) could end up with a stale, uninstalled class.Fix
Make the function idempotent: if the global is already patched (
_srvxmarker present), return the installedglobalThis.Requestimmediately instead of constructing a new class. This also removes the now-redundant assignment guard.Repeated calls now return the exact class installed as
globalThis.Request.Test
Added a regression test asserting that repeated
patchGlobalRequest()calls return the same class and that it is identical toglobalThis.Request(with the original global restored afterwards).Part of #249
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests