Path: blob/main/src/polyfill/bigint64array.js
4150 views
#if !POLYFILL1#error "this file should never be included unless POLYFILL is set"2#endif34if (typeof globalThis.BigInt64Array === "undefined") {5// BigInt64Array polyfill for Safari versions between v14.0 and v15.0.6// All browsers other than Safari added BigInt and BigInt64Array at the same7// time, but Safari introduced BigInt in v14.0 and introduced BigInt64Array in8// v15.0910function partsToBigIntSigned(lower, upper) {11return BigInt(lower) | (BigInt(upper + 2 * (upper & 0x80000000)) << 32n);12}1314function partsToBigIntUnsigned(lower, upper) {15return BigInt(lower) | (BigInt(upper) << 32n);16}1718function bigIntToParts(value) {19var lower = Number(BigInt(value) & BigInt(0xffffffff)) | 0;20var upper = Number(BigInt(value) >> 32n) | 0;21return [lower, upper];22}2324function createBigIntArrayShim(partsToBigInt) {25function createBigInt64Array(array) {26if (typeof array === "number") {27array = new Uint32Array(2 * array);28}29var orig_array;30if (!ArrayBuffer.isView(array)) {31if (array.constructor?.name === "ArrayBuffer") {32array = new Uint32Array(array);33} else {34orig_array = array;35array = new Uint32Array(array.length * 2);36}37}38var proxy = new Proxy(39{40slice(min, max) {41max ??= array.length;42var new_buf = array.slice(min * 2, max * 2);43return createBigInt64Array(new_buf);44},45subarray(min, max) {46var new_buf = array.subarray(min * 2, max * 2);47return createBigInt64Array(new_buf);48},49[Symbol.iterator]: function* () {50for (var i = 0; i < array.length / 2; i++) {51yield partsToBigInt(array[2 * i], array[2 * i + 1]);52}53},54BYTES_PER_ELEMENT: 2 * array.BYTES_PER_ELEMENT,55buffer: array.buffer,56byteLength: array.byteLength,57byteOffset: array.byteOffset,58length: array.length / 2,59copyWithin: function (target, start, end) {60array.copyWithin(target * 2, start * 2, end * 2);61return proxy;62},63set(source, targetOffset) {64targetOffset ??= 0;65if (2 * (source.length + targetOffset) > array.length) {66// This is the Chrome error message67// Firefox: "invalid or out-of-range index"68throw new RangeError("offset is out of bounds");69}70for (var i = 0; i < source.length; i++) {71var value = source[i];72var pair = bigIntToParts(value);73array.set(pair, 2 * (targetOffset + i));74}75},76},77{78get(target, idx, receiver) {79if (typeof idx !== "string" || !/^\d+$/.test(idx)) {80return Reflect.get(target, idx, receiver);81}82var lower = array[idx * 2];83var upper = array[idx * 2 + 1];84return partsToBigInt(lower, upper);85},86set(target, idx, value, receiver) {87if (typeof idx !== "string" || !/^\d+$/.test(idx)) {88return Reflect.set(target, idx, value, receiver);89}90if (typeof value !== "bigint") {91// Chrome error message, Firefox has no "a" in front if "BigInt".92throw new TypeError(`Cannot convert ${value} to a BigInt`);93}94var pair = bigIntToParts(value);95array.set(pair, 2 * idx);96return true;97},98}99);100if (orig_array) {101proxy.set(orig_array);102}103return proxy;104}105return createBigInt64Array;106}107108globalThis.BigUint64Array = createBigIntArrayShim(partsToBigIntUnsigned);109globalThis.BigInt64Array = createBigIntArrayShim(partsToBigIntSigned);110}111112113