Skip to content

Commit

Permalink
fix: support canonical module (#5040)
Browse files Browse the repository at this point in the history
* fix: handle canonicalizing Module

* fix: add tests for canonicalizing a module

* fix: skip module serialization on browser

* fix: handle more generic null prototype instead of Module

* fix: simplify null prototype check
  • Loading branch information
JacobLey authored Jul 20, 2024
1 parent 6d24689 commit 579e047
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
11 changes: 9 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function emptyRepresentation(value, typeHint) {
* canonicalType(global) // 'global'
* canonicalType(new String('foo') // 'object'
* canonicalType(async function() {}) // 'asyncfunction'
* canonicalType(await import(name)) // 'module'
* canonicalType(Object.create(null)) // 'null-prototype'
*/
var canonicalType = (exports.canonicalType = function canonicalType(value) {
if (value === undefined) {
Expand All @@ -147,7 +147,10 @@ var canonicalType = (exports.canonicalType = function canonicalType(value) {
return 'null';
} else if (Buffer.isBuffer(value)) {
return 'buffer';
} else if (Object.getPrototypeOf(value) === null) {
return 'null-prototype';
}

return Object.prototype.toString
.call(value)
.replace(/^\[.+\s(.+?)]$/, '$1')
Expand Down Expand Up @@ -213,7 +216,7 @@ exports.type = function type(value) {
exports.stringify = function (value) {
var typeHint = canonicalType(value);

if (!~['object', 'array', 'function'].indexOf(typeHint)) {
if (!~['object', 'array', 'function', 'null-prototype'].indexOf(typeHint)) {
if (typeHint === 'buffer') {
var json = Buffer.prototype.toJSON.call(value);
// Based on the toJSON result
Expand Down Expand Up @@ -399,8 +402,12 @@ exports.canonicalize = function canonicalize(value, stack, typeHint) {
break;
}
/* falls through */
case 'null-prototype':
case 'object':
canonicalizedObj = canonicalizedObj || {};
if (typeHint === 'null-prototype' && Symbol.toStringTag in value) {
canonicalizedObj['[Symbol.toStringTag]'] = value[Symbol.toStringTag];
}
withStack(value, function () {
Object.keys(value)
.sort()
Expand Down
38 changes: 38 additions & 0 deletions test/unit/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,44 @@ describe('lib/utils', function () {
].join('\n');
expect(stringify(expected), 'to be', actual);
});

describe('should represent null prototypes', function () {
it('With explicit names', function () {
const foo = Object.create(null, {
[Symbol.toStringTag]: {value: 'Foo'},
bing: {get: () => 'bong', enumerable: true}
});
const expected = [
'{',
' "[Symbol.toStringTag]": "Foo"',
' "bing": "bong"',
'}'
].join('\n');

expect(stringify(foo), 'to be', expected);
});

it('Without names', function () {
const unnamed = {
bing: 'bong',
abc: 123
};
unnamed.self = unnamed;
const expected = [
'{',
' "abc": 123',
' "bing": "bong"',
' "self": [Circular]',
'}'
].join('\n');

expect(
stringify(Object.setPrototypeOf(unnamed, null)),
'to be',
expected
);
});
});
});

it('should canonicalize the object', function () {
Expand Down

0 comments on commit 579e047

Please sign in to comment.