Skip to content

Commit 6d1a7cc

Browse files
author
Bob Lauer
authored
fix(utils): Account for null prototype during normalization (#6925)
It's possible for `Object.getPrototypeOf` to return `null` (when the object is created via `Object.create(null)`), in which case `null.constructor.name` will throw. If there is no prototype, this patch falls back to `null prototype`.
1 parent c0dcf41 commit 6d1a7cc

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

packages/utils/src/normalize.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,18 @@ function stringifyValue(
233233
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
234234
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
235235
// we can make sure that only plain objects come out that way.
236-
return `[object ${(Object.getPrototypeOf(value) as Prototype).constructor.name}]`;
236+
return `[object ${getConstructorName(value)}]`;
237237
} catch (err) {
238238
return `**non-serializable** (${err})`;
239239
}
240240
}
241241

242+
function getConstructorName(value: unknown): string {
243+
const prototype: Prototype | null = Object.getPrototypeOf(value);
244+
245+
return prototype ? prototype.constructor.name : 'null prototype';
246+
}
247+
242248
/** Calculates bytes size of input string */
243249
function utf8Length(value: string): number {
244250
// eslint-disable-next-line no-bitwise

packages/utils/test/normalize.test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ describe('normalize()', () => {
286286
expect(normalize([{ a }, { b: new B() }, c])).toEqual([{ a: 1 }, { b: 2 }, 3]);
287287
});
288288

289+
test('should return a normalized object even if a property was created without a prototype', () => {
290+
const subject = { a: 1, foo: Object.create(null), bar: Object.assign(Object.create(null), { baz: true }) } as any;
291+
expect(normalize(subject)).toEqual({ a: 1, foo: {}, bar: { baz: true } });
292+
});
293+
289294
test('should return a normalized object even if toJSON throws', () => {
290295
const subject = { a: 1, foo: 'bar' } as any;
291296
subject.toJSON = () => {

0 commit comments

Comments
 (0)