Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275const assert = require('node:assert');
function assertThrowsName(fn, name) { let thrown; try { fn(); } catch (error) { thrown = error; } assert(thrown, `expected ${name}`); assert.strictEqual(thrown.name, name);}
for (const Constructor of [ArrayBuffer, SharedArrayBuffer]) { assert.strictEqual(new Constructor().byteLength, 0); assert.strictEqual(new Constructor(undefined).byteLength, 0); assert.strictEqual(new Constructor(NaN).byteLength, 0); assert.strictEqual(new Constructor(-0.5).byteLength, 0); assert.strictEqual(new Constructor(3.9).byteLength, 3); assert.strictEqual(new Constructor('4').byteLength, 4); assert.strictEqual(new Constructor({ valueOf: () => 5 }).byteLength, 5);
assertThrowsName(() => new Constructor(-1), 'RangeError'); assertThrowsName(() => new Constructor(Infinity), 'RangeError'); assertThrowsName(() => new Constructor(-Infinity), 'RangeError'); assertThrowsName(() => new Constructor(2 ** 53), 'RangeError'); assertThrowsName(() => new Constructor(1n), 'TypeError'); assertThrowsName(() => new Constructor(Symbol('length')), 'TypeError');}
for (const Constructor of [Uint8Array, Uint32Array]) { assert.strictEqual(new Constructor(undefined).length, 0); assert.strictEqual(new Constructor(NaN).length, 0); assert.strictEqual(new Constructor(-0.5).length, 0); assert.strictEqual(new Constructor(3.9).length, 3); assert.strictEqual(new Constructor('4').length, 4);
assertThrowsName(() => new Constructor(-1), 'RangeError'); assertThrowsName(() => new Constructor(Infinity), 'RangeError'); assertThrowsName(() => new Constructor(2 ** 53), 'RangeError'); assertThrowsName(() => new Constructor(1n), 'TypeError'); assertThrowsName(() => new Constructor(Symbol('length')), 'TypeError');}
const arrayLike = new Uint8Array({ length: '3', 0: 7, 1: 8, 2: 9 });assert.deepStrictEqual([...arrayLike], [7, 8, 9]);assert.strictEqual(new Uint8Array({ length: -1 }).length, 0);assert.strictEqual(new Uint8Array({ length: -0.5 }).length, 0);
const typedBacking = new ArrayBuffer(16);assert.strictEqual(new Uint32Array(typedBacking, '4', '2').length, 2);assert.strictEqual(new Uint32Array(typedBacking, -0.5).byteOffset, 0);assert.strictEqual(new Uint32Array(typedBacking, 4, 2.9).length, 2);assert.strictEqual(new Uint32Array(typedBacking, 4, undefined).length, 3);assertThrowsName(() => new Uint32Array(typedBacking, -1), 'RangeError');assertThrowsName(() => new Uint32Array(typedBacking, 2), 'RangeError');assertThrowsName(() => new Uint32Array(typedBacking, 4, -1), 'RangeError');assertThrowsName(() => new Uint32Array(new ArrayBuffer(15)), 'RangeError');
const dataViewBacking = new ArrayBuffer(16);assert.strictEqual(new DataView(dataViewBacking, '4', '2').byteLength, 2);assert.strictEqual(new DataView(dataViewBacking, -0.5).byteOffset, 0);assert.strictEqual(new DataView(dataViewBacking, 4, 2.9).byteLength, 2);assert.strictEqual(new DataView(dataViewBacking, 4, undefined).byteLength, 12);assertThrowsName(() => new DataView(dataViewBacking, -1), 'RangeError');assertThrowsName(() => new DataView(dataViewBacking, 4, -1), 'RangeError');assertThrowsName(() => new DataView(dataViewBacking, 17), 'RangeError');
assert.strictEqual(new ArrayBuffer(8).transfer(undefined).byteLength, 8);assert.strictEqual(new ArrayBuffer(8).transfer(-0.5).byteLength, 0);assert.strictEqual(new ArrayBuffer(8).transfer(3.9).byteLength, 3);assert.strictEqual(new ArrayBuffer(8).transfer('4').byteLength, 4);assert.strictEqual(new ArrayBuffer(8).transferToFixedLength('4').byteLength, 4);
const failedTransfer = new ArrayBuffer(8);assertThrowsName(() => failedTransfer.transfer(-1), 'RangeError');assert.strictEqual(failedTransfer.detached, false);assertThrowsName(() => failedTransfer.transfer(Infinity), 'RangeError');assert.strictEqual(failedTransfer.detached, false);assertThrowsName(() => failedTransfer.transfer(1n), 'TypeError');assert.strictEqual(failedTransfer.detached, false);
const conversionError = new Error('conversion failed');let thrown;try { new DataView(dataViewBacking, { valueOf: () => { throw conversionError; } });} catch (error) { thrown = error;}assert.strictEqual(thrown, conversionError);
console.log('buffer:index-conversion:ok');
function assertThrowsValue(fn, expected) { let actual; try { fn(); } catch (error) { actual = error; } assert.strictEqual(actual, expected);}
for (const Constructor of [DataView, Uint8Array, Uint32Array]) { const offsetBacking = new ArrayBuffer(8); assertThrowsName(() => new Constructor(offsetBacking, { valueOf() { offsetBacking.transfer(); return 0; } }), 'TypeError');
const lengthBacking = new ArrayBuffer(8); assertThrowsName(() => new Constructor(lengthBacking, 4, { valueOf() { lengthBacking.transfer(); return 1; } }), 'TypeError');
const oversizedBacking = new ArrayBuffer(8); assertThrowsName(() => new Constructor(oversizedBacking, 4, { valueOf() { oversizedBacking.transfer(); return 1024; } }), Constructor === DataView ? 'RangeError' : 'TypeError');}
for (const method of ['transfer', 'transferToFixedLength']) { const backing = new ArrayBuffer(8); assertThrowsName(() => backing[method]({ valueOf() { backing.transfer(); return 1; } }), 'TypeError'); assert.strictEqual(backing.detached, true);}
for (const Constructor of [Uint8Array, Uint32Array, BigInt64Array]) { const expected = Constructor === BigInt64Array ? [7n, 8n] : [7, 8]; const source = new Constructor(expected); Object.defineProperty(source, Symbol.iterator, { get() { throw new Error('TypedArray copy must not read iterator'); } }); Object.defineProperty(source, 'length', { get() { throw new Error('TypedArray copy must use internal length'); } }); assert.deepStrictEqual([...new Constructor(source)], expected);}assert.deepStrictEqual([...new Uint32Array(new Uint8Array([7, 8]))], [7, 8]);assertThrowsName(() => new Uint8Array(new BigInt64Array(0)), 'TypeError');assertThrowsName(() => new BigInt64Array(new Uint8Array(0)), 'TypeError');const detachedSource = new Uint8Array(8);detachedSource.buffer.transfer();assertThrowsName(() => new Uint8Array(detachedSource), 'TypeError');
let iteratorGets = 0;let nextGets = 0;const iterableSource = { get length() { throw new Error('iterator must take precedence'); }, get [Symbol.iterator]() { iteratorGets++; return function () { assert.strictEqual(this, iterableSource); let index = 0; const iterator = { get next() { nextGets++; return function () { assert.strictEqual(this, iterator); const value = ++index; return { get done() { return value > 2; }, get value() { return value; } }; }; } }; return iterator; }; }};assert.deepStrictEqual([...new Uint8Array(iterableSource)], [1, 2]);assert.strictEqual(iteratorGets, 1);assert.strictEqual(nextGets, 1);
for (const stage of ['method', 'next-get', 'next-call', 'done', 'value']) { const expected = new Error(stage); const source = { length: 1, [Symbol.iterator]() { if (stage === 'method') throw expected; return { get next() { if (stage === 'next-get') throw expected; return function () { if (stage === 'next-call') throw expected; return { get done() { if (stage === 'done') throw expected; return false; }, get value() { throw expected; } }; }; } }; } }; assertThrowsValue(() => new Uint8Array(source), expected);}assertThrowsName(() => new Uint8Array({ length: 1, [Symbol.iterator]: 1 }), 'TypeError');assertThrowsName(() => new Uint8Array({ [Symbol.iterator]() { return 1; } }), 'TypeError');assertThrowsName(() => new Uint8Array({ [Symbol.iterator]() { return { next() { return 1; } }; } }), 'TypeError');assert.deepStrictEqual([...new Uint8Array({ length: 1, 0: 9, [Symbol.iterator]: null })], [9]);
const offsetSource = new Uint8Array(new Uint8Array([1, 7, 8, 2]).buffer, 1, 2);assert.deepStrictEqual([...new Uint8Array(offsetSource)], [7, 8]);assert.deepStrictEqual([...new Uint32Array(offsetSource)], [7, 8]);
let finishedIterating = false;const objectValues = { *[Symbol.iterator]() { for (let i = 0; i < 40; i++) { yield { valueOf() { assert.strictEqual(finishedIterating, true); return i; } }; } finishedIterating = true; }};assert.deepStrictEqual([...new Uint8Array(objectValues)], Array.from({ length: 40 }, (_, i) => i));assertThrowsName(() => new Uint8Array({ [Symbol.iterator]() { return { next: 1 }; } }), 'TypeError');
console.log('buffer:coercion-reentrancy-and-iteration:ok');
// The dense fast path must preserve iterator and conversion side effects.const numericArray = Array.from({ length: 4096 }, (_, i) => i & 255);assert.deepStrictEqual([...new Uint8Array(numericArray)], numericArray);const customArray = [1, 2];customArray[Symbol.iterator] = function* () { yield 9; };assert.deepStrictEqual([...new Uint8Array(customArray)], [9]);
const objectArray = [{ valueOf() { objectArray[1] = 99; return 1; } }, 2];assert.deepStrictEqual([...new Uint8Array(objectArray)], [1, 2]);let indexGets = 0;const getterArray = [1, 2];Object.defineProperty(getterArray, '0', { get() { indexGets++; getterArray[1] = 8; return 7; } });assert.deepStrictEqual([...new Uint8Array(getterArray)], [7, 8]);assert.strictEqual(indexGets, 1);const holeArray = [1, , 3];const holeProto = Object.create(Array.prototype);holeProto[1] = 8;Object.setPrototypeOf(holeArray, holeProto);assert.deepStrictEqual([...new Uint8Array(holeArray)], [1, 8, 3]);
const iteratorProto = Object.getPrototypeOf([][Symbol.iterator]());const originalNext = Object.getOwnPropertyDescriptor(iteratorProto, 'next');let nextCalls = 0;let customNextCopy;try { Object.defineProperty(iteratorProto, 'next', { configurable: true, writable: true, value() { nextCalls++; const step = originalNext.value.call(this); if (!step.done) step.value += 10; return step; } }); customNextCopy = new Uint8Array([1, 2]);} finally { Object.defineProperty(iteratorProto, 'next', originalNext);}assert.strictEqual(nextCalls, 3);assert.deepStrictEqual([...customNextCopy], [11, 12]);
let capturedIterator;const capturedArray = [3, 4];capturedArray[Symbol.iterator] = function () { capturedIterator = Array.prototype.values.call(this); return capturedIterator;};assert.deepStrictEqual([...new Uint8Array(capturedArray)], [3, 4]);assert.strictEqual(capturedIterator.next().done, true);const partiallyConsumed = [3, 4];partiallyConsumed[Symbol.iterator] = function () { const iterator = Array.prototype.values.call(this); iterator.next(); return iterator;};assert.deepStrictEqual([...new Uint8Array(partiallyConsumed)], [4]);const otherArray = [1, 2];otherArray[Symbol.iterator] = () => [8, 9][Symbol.iterator]();assert.deepStrictEqual([...new Uint8Array(otherArray)], [8, 9]);console.log('buffer:dense-array-fast-path:ok');