sidorares / json-bigint

JSON.parse/stringify with bigints support
MIT License
790 stars 189 forks source link

Understanding the protoAction behavior #50

Open mwilde345 opened 3 years ago

mwilde345 commented 3 years ago

Using deepStrictEqual, I assumed the equality check would pass when stringifying and parsing a simple object. But the Object prototype is still null after parsing with json-bigint, even with protoAction: 'preserve' set.

The check passes if I do assert.deepStrictEqual(Object.assign({}, parsed), a)

Is this intended? Is it simply because JSON.stringify doesn't preserve prototypes into __proto__ keys?

const JSONBig = require("json-bigint")({
  protoAction: "preserve",
});
var assert = require("assert");

const a = { result: "ok" };
const response = JSON.stringify(a);
const parsed = JSONBig.parse(response);

assert.deepStrictEqual(parsed, a);
/*
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

+ [Object: null prototype] {
- {
    result: 'ok'
  }
*/

Object.setPrototypeOf(parsed, {});
assert.deepStrictEqual(parsed, a);
/*
AssertionError [ERR_ASSERTION]: Values have same structure but are not reference-equal:

{
  result: 'ok'
}
*/
anusha5695 commented 2 years ago

@mwilde345, they seem to parse with base class as null instead of Object to prevent prototype pollution.

We had a use case where, after parsing we wanted all prototypes at nested levels in place and we ended up used lodash deepClone to re add the prototypes back at level

haoadoreorange commented 2 years ago

@mwilde345, they seem to parse with base class as null instead of Object to prevent prototype pollution.

We had a use case where, after parsing we wanted all prototypes at nested levels in place and we ended up used lodash deepClone to re add the prototypes back at level

To avoid prototype pollution I think it's enough to create the object with null prototype, and once proto get set, we can safely call setPrototypeOf upon the object.