Skip to content

Commit

Permalink
[Fix] node < v0.6 lacks proper Object toString behavior
Browse files Browse the repository at this point in the history
This also removes the `is-typed-array` dependency, which will be refactored to use this package instead
  • Loading branch information
ljharb committed Jul 18, 2023
1 parent e1734c9 commit b8fd654
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
77 changes: 55 additions & 22 deletions index.js
Expand Up @@ -13,44 +13,77 @@ var g = typeof globalThis === 'undefined' ? global : globalThis;
var typedArrays = availableTypedArrays();

var $slice = callBound('String.prototype.slice');
var toStrTags = { __proto__: null };
var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');

var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
for (var i = 0; i < array.length; i += 1) {
if (array[i] === value) {
return i;
}
}
return -1;
};
var cache = { __proto__: null };
if (hasToStringTag && gOPD && getPrototypeOf) {
forEach(typedArrays, function (typedArray) {
if (typeof g[typedArray] === 'function') {
var arr = new g[typedArray]();
if (Symbol.toStringTag in arr) {
var proto = getPrototypeOf(arr);
var descriptor = gOPD(proto, Symbol.toStringTag);
if (!descriptor) {
var superProto = getPrototypeOf(proto);
descriptor = gOPD(superProto, Symbol.toStringTag);
}
toStrTags[typedArray] = callBind(descriptor.get);
var arr = new g[typedArray]();
if (Symbol.toStringTag in arr) {
var proto = getPrototypeOf(arr);
var descriptor = gOPD(proto, Symbol.toStringTag);
if (!descriptor) {
var superProto = getPrototypeOf(proto);
descriptor = gOPD(superProto, Symbol.toStringTag);
}
cache['$' + typedArray] = callBind(descriptor.get);
}
});
} else {
forEach(typedArrays, function (typedArray) {
var arr = new g[typedArray]();
cache['$' + typedArray] = callBind(arr.slice);
});
}

var tryTypedArrays = function tryAllTypedArrays(value) {
var foundName = false;
forEach(toStrTags, function (getter, typedArray) {
if (!foundName) {
var found = false;
forEach(cache, function (getter, typedArray) {
if (!found) {
try {
var name = getter(value);
if (name === typedArray) {
foundName = name;
if ('$' + getter(value) === typedArray) {
found = $slice(typedArray, 1);
}
} catch (e) {}
} catch (e) { /**/ }
}
});
return foundName;
return found;
};

var isTypedArray = require('is-typed-array');
var trySlices = function tryAllSlices(value) {
var found = false;
forEach(cache, function (getter, name) {
if (!found) {
try {
getter(value);
found = $slice(name, 1);
} catch (e) { /**/ }
}
});
return found;
};

module.exports = function whichTypedArray(value) {
if (!isTypedArray(value)) { return false; }
if (!hasToStringTag || !(Symbol.toStringTag in value)) { return $slice($toString(value), 8, -1); }
if (!value || typeof value !== 'object') { return false; }
if (!hasToStringTag) {
var tag = $slice($toString(value), 8, -1);
if ($indexOf(typedArrays, tag) > -1) {
return tag;
}
if (tag !== 'Object') {
return false;
}
// node < 0.6 hits here on real Typed Arrays
return trySlices(value);
}
if (!gOPD) { return null; } // unknown engine
return tryTypedArrays(value);
};
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -62,8 +62,7 @@
"call-bind": "^1.0.2",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.10"
"has-tostringtag": "^1.0.0"
},
"devDependencies": {
"@ljharb/eslint-config": "^21.1.0",
Expand Down
2 changes: 1 addition & 1 deletion test/index.js
Expand Up @@ -90,7 +90,7 @@ test('Typed Arrays', function (t) {
var TypedArray = global[typedArray];
if (isCallable(TypedArray)) {
var arr = new TypedArray(10);
t.equal(typedArray, whichTypedArray(arr), 'new ' + typedArray + '(10) is typed array of type ' + typedArray);
t.equal(whichTypedArray(arr), typedArray, 'new ' + typedArray + '(10) is typed array of type ' + typedArray);
} else {
t.comment('# SKIP ' + typedArray + ' is not supported');
}
Expand Down

0 comments on commit b8fd654

Please sign in to comment.