1 | 'use strict';
|
---|
2 |
|
---|
3 | var forEach = require('for-each');
|
---|
4 | var availableTypedArrays = require('available-typed-arrays');
|
---|
5 | var callBind = require('call-bind');
|
---|
6 | var callBound = require('call-bind/callBound');
|
---|
7 | var gOPD = require('gopd');
|
---|
8 |
|
---|
9 | /** @type {(O: object) => string} */
|
---|
10 | var $toString = callBound('Object.prototype.toString');
|
---|
11 | var hasToStringTag = require('has-tostringtag/shams')();
|
---|
12 |
|
---|
13 | var g = typeof globalThis === 'undefined' ? global : globalThis;
|
---|
14 | var typedArrays = availableTypedArrays();
|
---|
15 |
|
---|
16 | var $slice = callBound('String.prototype.slice');
|
---|
17 | var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
|
---|
18 |
|
---|
19 | /** @type {<T = unknown>(array: readonly T[], value: unknown) => number} */
|
---|
20 | var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
|
---|
21 | for (var i = 0; i < array.length; i += 1) {
|
---|
22 | if (array[i] === value) {
|
---|
23 | return i;
|
---|
24 | }
|
---|
25 | }
|
---|
26 | return -1;
|
---|
27 | };
|
---|
28 |
|
---|
29 | /** @typedef {(receiver: import('.').TypedArray) => string | typeof Uint8Array.prototype.slice.call | typeof Uint8Array.prototype.set.call} Getter */
|
---|
30 | /** @type {{ [k in `\$${import('.').TypedArrayName}`]?: Getter } & { __proto__: null }} */
|
---|
31 | var cache = { __proto__: null };
|
---|
32 | if (hasToStringTag && gOPD && getPrototypeOf) {
|
---|
33 | forEach(typedArrays, function (typedArray) {
|
---|
34 | var arr = new g[typedArray]();
|
---|
35 | if (Symbol.toStringTag in arr) {
|
---|
36 | var proto = getPrototypeOf(arr);
|
---|
37 | // @ts-expect-error TS won't narrow inside a closure
|
---|
38 | var descriptor = gOPD(proto, Symbol.toStringTag);
|
---|
39 | if (!descriptor) {
|
---|
40 | var superProto = getPrototypeOf(proto);
|
---|
41 | // @ts-expect-error TS won't narrow inside a closure
|
---|
42 | descriptor = gOPD(superProto, Symbol.toStringTag);
|
---|
43 | }
|
---|
44 | // @ts-expect-error TODO: fix
|
---|
45 | cache['$' + typedArray] = callBind(descriptor.get);
|
---|
46 | }
|
---|
47 | });
|
---|
48 | } else {
|
---|
49 | forEach(typedArrays, function (typedArray) {
|
---|
50 | var arr = new g[typedArray]();
|
---|
51 | var fn = arr.slice || arr.set;
|
---|
52 | if (fn) {
|
---|
53 | // @ts-expect-error TODO: fix
|
---|
54 | cache['$' + typedArray] = callBind(fn);
|
---|
55 | }
|
---|
56 | });
|
---|
57 | }
|
---|
58 |
|
---|
59 | /** @type {(value: object) => false | import('.').TypedArrayName} */
|
---|
60 | var tryTypedArrays = function tryAllTypedArrays(value) {
|
---|
61 | /** @type {ReturnType<typeof tryAllTypedArrays>} */ var found = false;
|
---|
62 | forEach(
|
---|
63 | // eslint-disable-next-line no-extra-parens
|
---|
64 | /** @type {Record<`\$${TypedArrayName}`, Getter>} */ /** @type {any} */ (cache),
|
---|
65 | /** @type {(getter: Getter, name: `\$${import('.').TypedArrayName}`) => void} */
|
---|
66 | function (getter, typedArray) {
|
---|
67 | if (!found) {
|
---|
68 | try {
|
---|
69 | // @ts-expect-error TODO: fix
|
---|
70 | if ('$' + getter(value) === typedArray) {
|
---|
71 | found = $slice(typedArray, 1);
|
---|
72 | }
|
---|
73 | } catch (e) { /**/ }
|
---|
74 | }
|
---|
75 | }
|
---|
76 | );
|
---|
77 | return found;
|
---|
78 | };
|
---|
79 |
|
---|
80 | /** @type {(value: object) => false | import('.').TypedArrayName} */
|
---|
81 | var trySlices = function tryAllSlices(value) {
|
---|
82 | /** @type {ReturnType<typeof tryAllSlices>} */ var found = false;
|
---|
83 | forEach(
|
---|
84 | // eslint-disable-next-line no-extra-parens
|
---|
85 | /** @type {Record<`\$${TypedArrayName}`, Getter>} */ /** @type {any} */ (cache),
|
---|
86 | /** @type {(getter: typeof cache, name: `\$${import('.').TypedArrayName}`) => void} */ function (getter, name) {
|
---|
87 | if (!found) {
|
---|
88 | try {
|
---|
89 | // @ts-expect-error TODO: fix
|
---|
90 | getter(value);
|
---|
91 | found = $slice(name, 1);
|
---|
92 | } catch (e) { /**/ }
|
---|
93 | }
|
---|
94 | }
|
---|
95 | );
|
---|
96 | return found;
|
---|
97 | };
|
---|
98 |
|
---|
99 | /** @type {import('.')} */
|
---|
100 | module.exports = function whichTypedArray(value) {
|
---|
101 | if (!value || typeof value !== 'object') { return false; }
|
---|
102 | if (!hasToStringTag) {
|
---|
103 | /** @type {string} */
|
---|
104 | var tag = $slice($toString(value), 8, -1);
|
---|
105 | if ($indexOf(typedArrays, tag) > -1) {
|
---|
106 | return tag;
|
---|
107 | }
|
---|
108 | if (tag !== 'Object') {
|
---|
109 | return false;
|
---|
110 | }
|
---|
111 | // node < 0.6 hits here on real Typed Arrays
|
---|
112 | return trySlices(value);
|
---|
113 | }
|
---|
114 | if (!gOPD) { return null; } // unknown engine
|
---|
115 | return tryTypedArrays(value);
|
---|
116 | };
|
---|