Skip to content

Commit

Permalink
fix: handle more generic null prototype instead of Module
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobLey committed Apr 18, 2024
1 parent 8ccc02b commit b4b7066
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 32 deletions.
21 changes: 13 additions & 8 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,14 @@ var canonicalType = (exports.canonicalType = function canonicalType(value) {
return 'null';
} else if (Buffer.isBuffer(value)) {
return 'buffer';
} else if (
typeof value === 'object' &&
// eslint-disable-next-line no-prototype-builtins
!Object.prototype.isPrototypeOf(value)
) {
return 'null-prototype';
}

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

if (!~['object', 'array', 'function', 'module'].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,14 +406,12 @@ exports.canonicalize = function canonicalize(value, stack, typeHint) {
break;
}
/* falls through */
case 'module':
if (value[Symbol.toStringTag] === 'Module') {
canonicalizedObj = canonicalizedObj || {};
canonicalizedObj['[Symbol.toStringTag]'] = 'Module';
}
/* 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
4 changes: 0 additions & 4 deletions test/unit/fixtures/module.mjs

This file was deleted.

55 changes: 35 additions & 20 deletions test/unit/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
'use strict';

var utils = require('../../lib/utils');
const esmUtils = require('../../lib/nodejs/esm-utils');
const Path = require('node:path');
var sinon = require('sinon');

describe('lib/utils', function () {
Expand Down Expand Up @@ -291,25 +289,42 @@ describe('lib/utils', function () {
expect(stringify(expected), 'to be', actual);
});

it('should represent modules', async function () {
if (process.browser) {
// Current rollup config cannot `import()`
this.skip();
return;
}
const expected = await esmUtils.requireOrImport(
Path.join(__dirname, './fixtures/module.mjs')
);
const actual = [
'{',
' "[Symbol.toStringTag]": "Module"',
' "bar": true',
' "default": 123',
' "foo": "abc"',
'}'
].join('\n');
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);
});

expect(stringify(expected), 'to be', actual);
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
);
});
});
});

Expand Down

0 comments on commit b4b7066

Please sign in to comment.