Skip to content

Commit

Permalink
use toStringTag when available
Browse files Browse the repository at this point in the history
  • Loading branch information
planttheidea committed Sep 30, 2022
1 parent 656aab5 commit 53be968
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 29 deletions.
56 changes: 27 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ import {
copySelf,
copySet,
} from './copier';
import { createCache } from './utils';
import { createCache, getTag } from './utils';

import type { InternalCopier, State } from './copier';

export type { State } from './copier';

const { isArray } = Array;
const { getPrototypeOf } = Object;
const { toString } = Object.prototype;

export interface CreateCopierOptions {
array?: InternalCopier<any[]>;
Expand Down Expand Up @@ -51,29 +50,29 @@ export function createCopier(options: CreateCopierOptions) {
set = copySet,
} = options;

const typeSpecificCopiers: Record<string, InternalCopier> = {
'[object ArrayBuffer]': arrayBuffer,
'[object Blob]': blob,
'[object DataView]': dataView,
'[object Date]': date,
'[object Error]': error,
'[object Float32Array]': arrayBuffer,
'[object Float64Array]': arrayBuffer,
'[object Int8Array]': arrayBuffer,
'[object Int16Array]': arrayBuffer,
'[object Int32Array]': arrayBuffer,
'[object Map]': map,
'[object Object]': object,
'[object Promise]': copySelf,
'[object RegExp]': regExp,
'[object Set]': set,
'[object WeakMap]': copySelf,
'[object WeakSet]': copySelf,
'[object Uint8Array]': arrayBuffer,
'[object Uint8ClampedArray]': arrayBuffer,
'[object Uint16Array]': arrayBuffer,
'[object Uint32Array]': arrayBuffer,
'[object Uint64Array]': arrayBuffer,
const tagSpecificCopiers: Record<string, InternalCopier> = {
ArrayBuffer: arrayBuffer,
Blob: blob,
DataView: dataView,
Date: date,
Error: error,
Float32Array: arrayBuffer,
Float64Array: arrayBuffer,
Int8Array: arrayBuffer,
Int16Array: arrayBuffer,
Int32Array: arrayBuffer,
Map: map,
Object: object,
Promise: copySelf,
RegExp: regExp,
Set: set,
WeakMap: copySelf,
WeakSet: copySelf,
Uint8Array: arrayBuffer,
Uint8ClampedArray: arrayBuffer,
Uint16Array: arrayBuffer,
Uint32Array: arrayBuffer,
Uint64Array: arrayBuffer,
};

function copier(value: any, state: State): any {
Expand All @@ -100,11 +99,10 @@ export function createCopier(options: CreateCopierOptions) {
return array(value, state);
}

const objectType = toString.call(value);
const typeSpecificCopier = typeSpecificCopiers[objectType];
const tagSpecificCopier = tagSpecificCopiers[getTag(value)];

if (typeSpecificCopier) {
return typeSpecificCopier(value, state);
if (tagSpecificCopier) {
return tagSpecificCopier(value, state);
}

return typeof value.then === 'function' ? value : object(value, state);
Expand Down
17 changes: 17 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface Cache {

const { toString: toStringFunction } = Function.prototype;
const { create } = Object;
const { toString: toStringObject } = Object.prototype;

class LegacyCache {
_keys: any[] = [];
Expand Down Expand Up @@ -99,3 +100,19 @@ function getRegExpFlagsModern(regExp: RegExp): string {
*/
export const getRegExpFlags =
/test/g.flags === 'g' ? getRegExpFlagsModern : getRegExpFlagsLegacy;

function getTagLegacy(value: any): string {
const type = toStringObject.call(value);

return type.substring(8, type.length - 1);
}

function getTagModern(value: any): string {
return value[Symbol.toStringTag] || getTagLegacy(value);
}

/**
* Get the tag of the value passed, so that the correct copier can be used.
*/
export const getTag =
typeof Symbol !== 'undefined' ? getTagModern : getTagLegacy;

0 comments on commit 53be968

Please sign in to comment.