2c19b247de7b92b4343d8a25d5bc24cd1eadbadb2d4c9a645785a826577e33863aa9f8a29bc6db83c6394d94d821ea531139e0faefca8498235f84e248ade7 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use strict';
  2. var callBind = require('call-bind');
  3. var forEach = require('for-each');
  4. var gOPD = require('gopd');
  5. var hasProto = require('has-proto')();
  6. var isTypedArray = require('is-typed-array');
  7. var typedArrays = require('available-typed-arrays')();
  8. /** @typedef {import('possible-typed-array-names')[number]} TypedArrayName */
  9. /** @typedef {(value: import('.').TypedArray) => number} Getter */
  10. /** @type {Partial<Record<TypedArrayName, Getter> & { __proto__: null }>} */
  11. var getters = {
  12. __proto__: null
  13. };
  14. var oDP = Object.defineProperty;
  15. if (gOPD) {
  16. /** @type {Getter} */
  17. var getByteLength = function (x) {
  18. return x.byteLength;
  19. };
  20. forEach(typedArrays, function (typedArray) {
  21. // In Safari 7, Typed Array constructors are typeof object
  22. if (typeof global[typedArray] === 'function' || typeof global[typedArray] === 'object') {
  23. var TA = global[typedArray];
  24. /** @type {import('.').TypedArray} */
  25. var Proto = TA.prototype;
  26. // @ts-expect-error TS doesn't narrow properly inside callbacks
  27. var descriptor = gOPD(Proto, 'byteLength');
  28. if (!descriptor && hasProto) {
  29. // @ts-expect-error hush, TS, every object has a dunder proto
  30. var superProto = Proto.__proto__; // eslint-disable-line no-proto
  31. // @ts-expect-error TS doesn't narrow properly inside callbacks
  32. descriptor = gOPD(superProto, 'byteLength');
  33. }
  34. // Opera 12.16 has a magic byteLength data property on instances AND on Proto
  35. if (descriptor && descriptor.get) {
  36. getters[typedArray] = callBind(descriptor.get);
  37. } else if (oDP) {
  38. // this is likely an engine where instances have a magic byteLength data property
  39. var arr = new global[typedArray](2);
  40. // @ts-expect-error TS doesn't narrow properly inside callbacks
  41. descriptor = gOPD(arr, 'byteLength');
  42. if (descriptor && descriptor.configurable) {
  43. oDP(arr, 'length', { value: 3 });
  44. }
  45. if (arr.length === 2) {
  46. getters[typedArray] = getByteLength;
  47. }
  48. }
  49. }
  50. });
  51. }
  52. /** @type {Getter} */
  53. var tryTypedArrays = function tryAllTypedArrays(value) {
  54. /** @type {number} */ var foundByteLength;
  55. forEach(
  56. // eslint-disable-next-line no-extra-parens
  57. /** @type {Record<TypedArrayName, Getter>} */ (getters),
  58. /** @type {(getter: Getter) => void} */ function (getter) {
  59. if (typeof foundByteLength !== 'number') {
  60. try {
  61. var byteLength = getter(value);
  62. if (typeof byteLength === 'number') {
  63. foundByteLength = byteLength;
  64. }
  65. } catch (e) {}
  66. }
  67. }
  68. );
  69. // @ts-expect-error TS can't guarantee the callback is invoked sync
  70. return foundByteLength;
  71. };
  72. /** @type {import('.')} */
  73. module.exports = function typedArrayByteLength(value) {
  74. if (!isTypedArray(value)) {
  75. return false;
  76. }
  77. return tryTypedArrays(value);
  78. };