Conversation
An own `constructor` key shadowed the class lookup in `serializeObject`.
`{ constructor: null }` threw on `.name`, `{ constructor: 1 }` produced an
`undefined` prefix, and a value equal to a global (`{ constructor: Date }`)
selected that type's handler.
Such a key is trivial to produce — `JSON.parse` output, a query object, any
user supplied record — so reading it as the object's class is never correct.
Reading the constructor from the prototype keeps the class detection intact
for real class instances while treating an own key as plain data.
The gzipped `hash` bundle budget goes from 1550 to 1560 bytes (1548 -> 1559)
for the `Object.getPrototypeOf` call.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughObject serialization now reads the constructor from the prototype chain. Tests cover own ChangesConstructor serialization
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Low Suggested reviewers: Merge Risk: ⚪ Minimal · up to The serialization fix addresses own constructor-property handling without an identified remaining correctness or availability risk. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #207 +/- ##
===========================================
+ Coverage 80.31% 95.66% +15.34%
===========================================
Files 8 6 -2
Lines 1006 369 -637
Branches 111 94 -17
===========================================
- Hits 808 353 -455
+ Misses 198 13 -185
- Partials 0 3 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Problem
serializeObjectreads the object's class withobject.constructor, which resolves an ownconstructorkey before the prototype one. Such a key is easy to produce —JSON.parseoutput, a parsed query object, any user supplied record — and it currently breaks serialization three different ways:The first case is the worst one:
hash(JSON.parse(userJson))throws instead of returning a hash, so a cache key or an ETag computed from untrusted JSON can take down the request. The third is subtler —globalThis[objName] === constructorpasses because the own value is the global, so a plain object is routed through$Date/$Map/ ... and either throws or hashes as something it is not.Fix
Read the constructor from the prototype instead of from the object:
Class detection is unchanged for real instances (
new Test()still hasTeston its prototype), and an ownconstructorkey is now treated as ordinary data:?.coversObject.create(null), which previously landed on theconstructor === undefinedbranch and still resolves to"".Bundle size
The
hashgzip budget needed +10 bytes (1548 → 1559) for theObject.getPrototypeOfcall, so the assertion moves from 1550 to 1560. Theserializeanddiffbudgets are unchanged. Happy to drop the budget change and shrink this differently if you would rather hold the line at 1.55 kB.Tests
New
own \constructor` keycase intest/serialize.test.tscovering the throw, theundefinedprefix,JSON.parseinput, the global-collision path, and that distinct values still hash distinctly. Full suite green: 91 passed, pluslintandtest:types`.Summary by CodeRabbit
constructorproperty, including data parsed from JSON.