fix(client): fix browser-imported Prisma.DbNull producing empty object#29286
Conversation
…DbNull
Replace `instanceof ObjectEnumValue` checks with duck-typing via a new
`isObjectEnumValue()` function. This fixes Prisma.DbNull from the
browser entry point producing `{}` instead of NULL when passed to
PrismaClient in bundled environments like Next.js.
Fixes prisma#29257
|
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughIntroduces a cross-bundle type guard Changes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
packages/client-runtime-utils/src/nullTypes.tspackages/client/src/runtime/core/errorRendering/ArgumentsRenderingTree.tspackages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.tspackages/client/src/runtime/index-browser.tspackages/client/src/runtime/index.tspackages/client/src/runtime/utils/deepCloneArgs.ts
|
Thanks for the PR! The changes do not include any tests. Could you add a test based on the reported issue in |
Verifies DbNull, JsonNull, and AnyNull from the browser entry expose _getName() and _getNamespace() methods used by isObjectEnumValue() for duck-typing detection across bundle boundaries.
|
added a test in the existing browser-bundle e2e suite (c2c72b5) that verifies DbNull, JsonNull, and AnyNull from the browser entry expose _getName() and _getNamespace() — the duck-typing methods that isObjectEnumValue() relies on for cross-bundle detection. couldn't run the e2e suite locally since it needs docker + tarball packing, but verified the underlying logic directly against the built runtime — isObjectEnumValue correctly identifies all three null types and works with cross-bundle instances where instanceof fails. |
|
I think the newly added test isn't sufficient, we need something that prevents future regression, ideally something that looks like a minimized reproduction of the original issue. |
…tion Simulates the cross-bundle scenario (e.g. Next.js bundling browser and server code separately) by creating plain objects with the duck-typing interface instead of real ObjectEnumValue instances.
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.tspackages/client/src/runtime/utils/deepCloneArgs.test.ts
packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts
Show resolved
Hide resolved
|
i have updated the test do correct me if i got something wrong, thanks for the review! |
Replace duck-typing (_getName/_getNamespace method checks) with a
global symbol (Symbol.for('prisma.objectEnumValue')) for identifying
ObjectEnumValue instances across bundle boundaries. This is more
explicitly Prisma-specific and avoids false positives from unrelated
objects that happen to have similar methods.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts (1)
795-880:⚠️ Potential issue | 🟠 MajorSerializer snapshots are good, but please verify a true e2e persistence regression test exists.
These tests validate JSON protocol serialization, not the original failure mode (browser import +
create()+ DB persisted{}vsNULL). Please confirm an e2e test covers that exact flow.#!/bin/bash # Verify whether e2e tests cover browser-imported DbNull persistence to DB. # Expected: at least one e2e test importing from browser entry and asserting persisted NULL behavior. rg -nP -C3 --type=ts \ "generated/prisma/browser|DbNull|JsonNull|AnyNull|create\(|json.*null|NULL" \ packages/client/tests/e2e
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: c9c3962b-43d1-4c02-adf0-0540a01c04bf
📒 Files selected for processing (3)
packages/client-runtime-utils/src/nullTypes.tspackages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.tspackages/client/src/runtime/utils/deepCloneArgs.test.ts
|
There's a failing |
Custom ObjectEnumValue instances are now accepted because we use a global symbol for detection instead of singleton equality checks. This is necessary for cross-bundle support — a singleton from a different bundle is indistinguishable from a custom instance.
|
fixed it, thanks for the review |
Merging this PR will degrade performance by 98.99%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | compile blog post page (uncached baseline) |
3.5 ms | 346.1 ms | -98.99% |
Comparing Not-Sarthak:fix/browser-dbnull-cross-bundle (d840457) with main (7a1f497)
Footnotes
-
30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
Summary
Fixes #29257
When importing
Prisma.DbNullfrom the browser entry point (./generated/prisma/browser) and passing it toprisma.create()in a bundled environment like Next.js, the value is serialized as{}instead ofNULL.Root cause: The serialization code uses
instanceof ObjectEnumValueto detectDbNull/JsonNull/AnyNullvalues. In bundled environments (e.g., Next.js with webpack/turbopack), the browser and server entry points may resolve to separate copies of@prisma/client-runtime-utils, creating different class instances. Theinstanceofcheck fails across these bundle boundaries, causingDbNullto fall through to the generic object serialization path and become{}.Fix: Replace all
instanceof ObjectEnumValuechecks with a newisObjectEnumValue()duck-typing function that checks for the_getNameand_getNamespacemethods. This follows the existingisDecimalJsLikepattern already used in the codebase for cross-bundle Decimal detection.Changes
client-runtime-utils/src/nullTypes.ts: AddisObjectEnumValue()duck-typing functionclient/src/runtime/index-browser.ts: ExportisObjectEnumValueclient/src/runtime/index.ts: ExportisObjectEnumValueclient/src/runtime/core/jsonProtocol/serializeJsonQuery.ts: UseisObjectEnumValue()instead ofinstanceof ObjectEnumValue; validate by name string instead of singleton identityclient/src/runtime/utils/deepCloneArgs.ts: UseisObjectEnumValue()instead ofinstanceof ObjectEnumValueclient/src/runtime/core/errorRendering/ArgumentsRenderingTree.ts: UseisObjectEnumValue()instead ofinstanceof ObjectEnumValueTest plan
serializeJsonQuerytests passdeepCloneArgstests passArgumentsRenderingTreetests passSummary by CodeRabbit
New Features
Bug Fixes
Tests