Skip to content

Commit 3ede13e

Browse files
authored
fix(NODE-6552): remove cache and use toStringTag in type helpers (#740)
1 parent dbeda2f commit 3ede13e

File tree

1 file changed

+30
-51
lines changed

1 file changed

+30
-51
lines changed

src/parser/utils.ts

+30-51
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,44 @@
1-
const map = new WeakMap<object, string>();
1+
const TypedArrayPrototypeGetSymbolToStringTag = (() => {
2+
// Type check system lovingly referenced from:
3+
// https://github.com/nodejs/node/blob/7450332339ed40481f470df2a3014e2ec355d8d8/lib/internal/util/types.js#L13-L15
4+
// eslint-disable-next-line @typescript-eslint/unbound-method -- the intention is to call this method with a bound value
5+
const g = Object.getOwnPropertyDescriptor(
6+
Object.getPrototypeOf(Uint8Array.prototype),
7+
Symbol.toStringTag
8+
)!.get!;
29

3-
const TYPES = {
4-
ArrayBuffer: '[object ArrayBuffer]',
5-
SharedArrayBuffer: '[object SharedArrayBuffer]',
6-
Uint8Array: '[object Uint8Array]',
7-
BigInt64Array: '[object BigInt64Array]',
8-
BigUint64Array: '[object BigUint64Array]',
9-
RegExp: '[object RegExp]',
10-
Map: '[object Map]',
11-
Date: '[object Date]'
12-
};
13-
14-
/**
15-
* Retrieves the prototype.toString() of a value.
16-
* If the value is an object, it will cache the result in a WeakMap for future use.
17-
*/
18-
function getPrototypeString(value: unknown): string {
19-
let str = map.get(value as object);
20-
21-
if (!str) {
22-
str = Object.prototype.toString.call(value);
23-
if (value !== null && typeof value === 'object') {
24-
map.set(value, str);
25-
}
26-
}
27-
return str;
28-
}
29-
30-
export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer {
31-
const type = getPrototypeString(value);
32-
return type === TYPES.ArrayBuffer || type === TYPES.SharedArrayBuffer;
33-
}
10+
return (value: unknown) => g.call(value);
11+
})();
3412

3513
export function isUint8Array(value: unknown): value is Uint8Array {
36-
const type = getPrototypeString(value);
37-
return type === TYPES.Uint8Array;
14+
return TypedArrayPrototypeGetSymbolToStringTag(value) === 'Uint8Array';
3815
}
3916

40-
export function isBigInt64Array(value: unknown): value is BigInt64Array {
41-
const type = getPrototypeString(value);
42-
return type === TYPES.BigInt64Array;
43-
}
44-
45-
export function isBigUInt64Array(value: unknown): value is BigUint64Array {
46-
const type = getPrototypeString(value);
47-
return type === TYPES.BigUint64Array;
17+
export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer {
18+
return (
19+
typeof value === 'object' &&
20+
value != null &&
21+
Symbol.toStringTag in value &&
22+
(value[Symbol.toStringTag] === 'ArrayBuffer' ||
23+
value[Symbol.toStringTag] === 'SharedArrayBuffer')
24+
);
4825
}
4926

50-
export function isRegExp(d: unknown): d is RegExp {
51-
const type = getPrototypeString(d);
52-
return type === TYPES.RegExp;
27+
export function isRegExp(regexp: unknown): regexp is RegExp {
28+
return regexp instanceof RegExp || Object.prototype.toString.call(regexp) === '[object RegExp]';
5329
}
5430

55-
export function isMap(d: unknown): d is Map<unknown, unknown> {
56-
const type = getPrototypeString(d);
57-
return type === TYPES.Map;
31+
export function isMap(value: unknown): value is Map<unknown, unknown> {
32+
return (
33+
typeof value === 'object' &&
34+
value != null &&
35+
Symbol.toStringTag in value &&
36+
value[Symbol.toStringTag] === 'Map'
37+
);
5838
}
5939

60-
export function isDate(d: unknown): d is Date {
61-
const type = getPrototypeString(d);
62-
return type === TYPES.Date;
40+
export function isDate(date: unknown): date is Date {
41+
return date instanceof Date || Object.prototype.toString.call(date) === '[object Date]';
6342
}
6443

6544
export type InspectFn = (x: unknown, options?: unknown) => string;

0 commit comments

Comments
 (0)