MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tests

+2650 -1
+105
examples/spec/arrays.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Array Tests\n'); 4 + 5 + let arr = [1, 2, 3]; 6 + test('array literal creates array', arr instanceof Array, true); 7 + test('array index 0', arr[0], 1); 8 + test('array index 1', arr[1], 2); 9 + test('array index 2', arr[2], 3); 10 + test('array length', arr.length, 3); 11 + 12 + let empty = []; 13 + test('empty array is array', empty instanceof Array, true); 14 + test('empty array length', empty.length, 0); 15 + 16 + let mixed = [1, 'hello', true, null]; 17 + test('mixed array length', mixed.length, 4); 18 + test('mixed array string', mixed[1], 'hello'); 19 + test('mixed array bool', mixed[2], true); 20 + test('mixed array null', mixed[3], null); 21 + 22 + arr[0] = 10; 23 + test('array assignment', arr[0], 10); 24 + 25 + arr.push(4); 26 + test('push adds element', arr[arr.length - 1], 4); 27 + test('push increases length', arr.length, 4); 28 + 29 + arr.push(5, 6); 30 + test('push multiple', arr.length, 6); 31 + 32 + let popped = arr.pop(); 33 + test('pop returns last', popped, 6); 34 + test('pop decreases length', arr.length, 5); 35 + 36 + let nested = [[1, 2], [3, 4]]; 37 + test('nested array access', nested[0][0], 1); 38 + test('nested array access deep', nested[1][1], 4); 39 + 40 + let arr2 = Array(3); 41 + test('Array(n) creates sparse', arr2.length, 3); 42 + 43 + let arr3 = Array(10, 20, 30); 44 + test('Array with elements', arr3.length, 3); 45 + test('Array with elements value', arr3[1], 20); 46 + 47 + test('instanceof Array true', [1,2] instanceof Array, true); 48 + test('instanceof Array false for object', ({}) instanceof Array, false); 49 + 50 + let obj = [1, 2, 3]; 51 + obj['foo'] = 'bar'; 52 + test('array string key', obj.foo, 'bar'); 53 + 54 + let sumArr = [1, 2, 3, 4]; 55 + let sum = 0; 56 + for (let i = 0; i < sumArr.length; i++) sum += sumArr[i]; 57 + test('array iteration sum', sum, 10); 58 + 59 + let a = [1, 2, 3]; 60 + testDeep('concat arrays', a.concat([4, 5]), [1, 2, 3, 4, 5]); 61 + test('join with comma', a.join(','), '1,2,3'); 62 + test('indexOf found', a.indexOf(2), 1); 63 + test('indexOf not found', a.indexOf(5), -1); 64 + test('includes true', a.includes(2), true); 65 + test('includes false', a.includes(5), false); 66 + testDeep('slice', a.slice(1, 3), [2, 3]); 67 + testDeep('reverse', [1, 2, 3].reverse(), [3, 2, 1]); 68 + 69 + let shifted = [1, 2, 3]; 70 + test('shift returns first', shifted.shift(), 1); 71 + test('shift decreases length', shifted.length, 2); 72 + 73 + let unshifted = [2, 3]; 74 + unshifted.unshift(1); 75 + test('unshift adds to front', unshifted[0], 1); 76 + test('unshift increases length', unshifted.length, 3); 77 + 78 + testDeep('map', [1, 2, 3].map(x => x * 2), [2, 4, 6]); 79 + testDeep('filter', [1, 2, 3, 4].filter(x => x % 2 === 0), [2, 4]); 80 + test('reduce sum', [1, 2, 3].reduce((a, b) => a + b, 0), 6); 81 + test('find', [1, 2, 3].find(x => x > 1), 2); 82 + test('findIndex', [1, 2, 3].findIndex(x => x > 1), 1); 83 + test('every true', [2, 4, 6].every(x => x % 2 === 0), true); 84 + test('every false', [2, 3, 6].every(x => x % 2 === 0), false); 85 + test('some true', [1, 2, 3].some(x => x > 2), true); 86 + test('some false', [1, 2, 3].some(x => x > 5), false); 87 + 88 + testDeep('Array.from string', Array.from('abc'), ['a', 'b', 'c']); 89 + testDeep('Array.of', Array.of(1, 2, 3), [1, 2, 3]); 90 + test('instanceof Array true', [] instanceof Array, true); 91 + test('instanceof Array false', ({}) instanceof Array, false); 92 + 93 + testDeep('flat', [1, [2, 3]].flat(), [1, 2, 3]); 94 + testDeep('flatMap', [1, 2].flatMap(x => [x, x * 2]), [1, 2, 2, 4]); 95 + 96 + let filled = new Array(3).fill(0); 97 + testDeep('fill', filled, [0, 0, 0]); 98 + 99 + let sorted = [3, 1, 2].sort(); 100 + testDeep('sort default', sorted, [1, 2, 3]); 101 + 102 + let sortedDesc = [1, 2, 3].sort((a, b) => b - a); 103 + testDeep('sort descending', sortedDesc, [3, 2, 1]); 104 + 105 + summary();
+72
examples/spec/async.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Async/Await Tests\n'); 4 + 5 + let results = {}; 6 + 7 + async function basicAsync() { 8 + return 42; 9 + } 10 + basicAsync().then(v => { results.basic = v; }); 11 + 12 + const arrowAsync = async () => 'arrow result'; 13 + arrowAsync().then(v => { results.arrow = v; }); 14 + 15 + const singleParam = async x => x * 2; 16 + singleParam(21).then(v => { results.singleParam = v; }); 17 + 18 + const multiParam = async (a, b) => a + b; 19 + multiParam(10, 32).then(v => { results.multiParam = v; }); 20 + 21 + async function withPromise() { 22 + return Promise.resolve('promise from async'); 23 + } 24 + withPromise().then(v => { results.withPromise = v; }); 25 + 26 + async function conditional(flag) { 27 + if (flag) return 'true branch'; 28 + return 'false branch'; 29 + } 30 + conditional(true).then(v => { results.condTrue = v; }); 31 + conditional(false).then(v => { results.condFalse = v; }); 32 + 33 + const obj = { 34 + value: 100, 35 + asyncMethod: async function () { 36 + return this.value; 37 + } 38 + }; 39 + obj.asyncMethod().then(v => { results.objMethod = v; }); 40 + 41 + Promise.resolve(1) 42 + .then(v => v + 1) 43 + .then(v => v + 1) 44 + .then(v => v + 1) 45 + .then(v => { results.chain = v; }); 46 + 47 + async function awaiter() { 48 + const a = await Promise.resolve(1); 49 + const b = await Promise.resolve(2); 50 + return a + b; 51 + } 52 + awaiter().then(v => { results.awaiter = v; }); 53 + 54 + async function awaitValue() { 55 + return await 42; 56 + } 57 + awaitValue().then(v => { results.awaitValue = v; }); 58 + 59 + setTimeout(() => { 60 + test('basic async', results.basic, 42); 61 + test('arrow async', results.arrow, 'arrow result'); 62 + test('single param async', results.singleParam, 42); 63 + test('multi param async', results.multiParam, 42); 64 + test('with promise', results.withPromise, 'promise from async'); 65 + test('conditional true', results.condTrue, 'true branch'); 66 + test('conditional false', results.condFalse, 'false branch'); 67 + test('object method', results.objMethod, 100); 68 + test('promise chain', results.chain, 4); 69 + test('awaiter sum', results.awaiter, 3); 70 + test('await value', results.awaitValue, 42); 71 + summary(); 72 + }, 50);
+41
examples/spec/atomics.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Atomics Tests\n'); 4 + 5 + const sab = new SharedArrayBuffer(16); 6 + const int32 = new Int32Array(sab); 7 + 8 + Atomics.store(int32, 0, 42); 9 + test('Atomics.store/load', Atomics.load(int32, 0), 42); 10 + 11 + test('Atomics.add', Atomics.add(int32, 0, 10), 42); 12 + test('after add', Atomics.load(int32, 0), 52); 13 + 14 + test('Atomics.sub', Atomics.sub(int32, 0, 2), 52); 15 + test('after sub', Atomics.load(int32, 0), 50); 16 + 17 + Atomics.store(int32, 1, 0b1010); 18 + test('Atomics.and', Atomics.and(int32, 1, 0b1100), 0b1010); 19 + test('after and', Atomics.load(int32, 1), 0b1000); 20 + 21 + Atomics.store(int32, 2, 0b1010); 22 + test('Atomics.or', Atomics.or(int32, 2, 0b0101), 0b1010); 23 + test('after or', Atomics.load(int32, 2), 0b1111); 24 + 25 + Atomics.store(int32, 3, 0b1010); 26 + test('Atomics.xor', Atomics.xor(int32, 3, 0b1100), 0b1010); 27 + test('after xor', Atomics.load(int32, 3), 0b0110); 28 + 29 + Atomics.store(int32, 0, 10); 30 + test('Atomics.exchange', Atomics.exchange(int32, 0, 20), 10); 31 + test('after exchange', Atomics.load(int32, 0), 20); 32 + 33 + Atomics.store(int32, 0, 5); 34 + test('Atomics.compareExchange match', Atomics.compareExchange(int32, 0, 5, 10), 5); 35 + test('after compareExchange', Atomics.load(int32, 0), 10); 36 + 37 + Atomics.store(int32, 0, 5); 38 + test('Atomics.compareExchange no match', Atomics.compareExchange(int32, 0, 99, 10), 5); 39 + test('after no match', Atomics.load(int32, 0), 5); 40 + 41 + summary();
+29
examples/spec/base64.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Base64 Tests\n'); 4 + 5 + test('btoa Hello World', btoa('Hello, World!'), 'SGVsbG8sIFdvcmxkIQ=='); 6 + test('atob Hello World', atob('SGVsbG8sIFdvcmxkIQ=='), 'Hello, World!'); 7 + 8 + const original = 'The quick brown fox jumps over the lazy dog'; 9 + test('roundtrip', atob(btoa(original)), original); 10 + 11 + test('btoa empty', btoa(''), ''); 12 + test('atob empty', atob(''), ''); 13 + 14 + test('btoa single char', btoa('A'), 'QQ=='); 15 + test('btoa two chars', btoa('AB'), 'QUI='); 16 + test('btoa three chars', btoa('ABC'), 'QUJD'); 17 + 18 + test('roundtrip numbers', atob(btoa('12345')), '12345'); 19 + 20 + const special = '!@#$%^&*()'; 21 + test('roundtrip special', atob(btoa(special)), special); 22 + 23 + const jsonData = '{"name":"test","value":123}'; 24 + test('roundtrip json', atob(btoa(jsonData)), jsonData); 25 + 26 + test('btoa binary', btoa('\x00\x01\x02'), 'AAEC'); 27 + test('atob binary', atob('AAEC'), '\x00\x01\x02'); 28 + 29 + summary();
+29
examples/spec/bigint.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('BigInt Tests\n'); 4 + 5 + test('bigint literal', 123n, 123n); 6 + test('BigInt()', BigInt(456), 456n); 7 + test('BigInt from string', BigInt('789'), 789n); 8 + 9 + test('bigint addition', 1n + 2n, 3n); 10 + test('bigint subtraction', 10n - 3n, 7n); 11 + test('bigint multiplication', 4n * 5n, 20n); 12 + test('bigint division', 10n / 3n, 3n); 13 + test('bigint modulo', 10n % 3n, 1n); 14 + test('bigint exponentiation', 2n ** 10n, 1024n); 15 + 16 + test('bigint comparison <', 1n < 2n, true); 17 + test('bigint comparison >', 5n > 3n, true); 18 + test('bigint comparison ===', 5n === 5n, true); 19 + test('bigint comparison ==', 5n == 5, true); 20 + 21 + test('typeof bigint', typeof 123n, 'bigint'); 22 + 23 + test('large bigint', 9007199254740993n > 9007199254740991n, true); 24 + 25 + test('bigint negation', -5n, -5n); 26 + 27 + test('bigint toString', (255n).toString(16), 'ff'); 28 + 29 + summary();
+123
examples/spec/buffer.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Buffer Tests\n'); 4 + 5 + const ab = new ArrayBuffer(16); 6 + test('ArrayBuffer byteLength', ab.byteLength, 16); 7 + 8 + const ab2 = ab.slice(4, 12); 9 + test('ArrayBuffer slice byteLength', ab2.byteLength, 8); 10 + 11 + const u8 = new Uint8Array(8); 12 + test('Uint8Array length', u8.length, 8); 13 + test('Uint8Array byteLength', u8.byteLength, 8); 14 + test('Uint8Array BYTES_PER_ELEMENT', u8.BYTES_PER_ELEMENT, 1); 15 + 16 + const i16 = new Int16Array(4); 17 + test('Int16Array length', i16.length, 4); 18 + test('Int16Array byteLength', i16.byteLength, 8); 19 + test('Int16Array BYTES_PER_ELEMENT', i16.BYTES_PER_ELEMENT, 2); 20 + 21 + const i32 = new Int32Array(2); 22 + test('Int32Array length', i32.length, 2); 23 + test('Int32Array byteLength', i32.byteLength, 8); 24 + test('Int32Array BYTES_PER_ELEMENT', i32.BYTES_PER_ELEMENT, 4); 25 + 26 + const f32 = new Float32Array(4); 27 + test('Float32Array length', f32.length, 4); 28 + test('Float32Array byteLength', f32.byteLength, 16); 29 + test('Float32Array BYTES_PER_ELEMENT', f32.BYTES_PER_ELEMENT, 4); 30 + 31 + const f64 = new Float64Array(2); 32 + test('Float64Array length', f64.length, 2); 33 + test('Float64Array byteLength', f64.byteLength, 16); 34 + test('Float64Array BYTES_PER_ELEMENT', f64.BYTES_PER_ELEMENT, 8); 35 + 36 + const u16 = new Uint16Array(4); 37 + test('Uint16Array length', u16.length, 4); 38 + test('Uint16Array BYTES_PER_ELEMENT', u16.BYTES_PER_ELEMENT, 2); 39 + 40 + const u32 = new Uint32Array(2); 41 + test('Uint32Array length', u32.length, 2); 42 + test('Uint32Array BYTES_PER_ELEMENT', u32.BYTES_PER_ELEMENT, 4); 43 + 44 + const i8 = new Int8Array(8); 45 + test('Int8Array length', i8.length, 8); 46 + test('Int8Array BYTES_PER_ELEMENT', i8.BYTES_PER_ELEMENT, 1); 47 + 48 + const u8c = new Uint8ClampedArray(8); 49 + test('Uint8ClampedArray length', u8c.length, 8); 50 + test('Uint8ClampedArray BYTES_PER_ELEMENT', u8c.BYTES_PER_ELEMENT, 1); 51 + 52 + const bi64 = new BigInt64Array(2); 53 + test('BigInt64Array length', bi64.length, 2); 54 + test('BigInt64Array BYTES_PER_ELEMENT', bi64.BYTES_PER_ELEMENT, 8); 55 + 56 + const bu64 = new BigUint64Array(2); 57 + test('BigUint64Array length', bu64.length, 2); 58 + test('BigUint64Array BYTES_PER_ELEMENT', bu64.BYTES_PER_ELEMENT, 8); 59 + 60 + const buffer = new ArrayBuffer(16); 61 + const view8 = new Uint8Array(buffer); 62 + const view16 = new Uint16Array(buffer); 63 + const view32 = new Uint32Array(buffer); 64 + 65 + test('Uint8Array view length', view8.length, 16); 66 + test('Uint16Array view length', view16.length, 8); 67 + test('Uint32Array view length', view32.length, 4); 68 + 69 + const viewWithOffset = new Uint8Array(buffer, 4); 70 + test('view with offset length', viewWithOffset.length, 12); 71 + test('view with offset byteOffset', viewWithOffset.byteOffset, 4); 72 + 73 + const viewWithOffsetAndLength = new Uint8Array(buffer, 4, 8); 74 + test('view offset+length length', viewWithOffsetAndLength.length, 8); 75 + test('view offset+length byteOffset', viewWithOffsetAndLength.byteOffset, 4); 76 + 77 + const dv = new DataView(buffer); 78 + test('DataView byteLength', dv.byteLength, 16); 79 + test('DataView byteOffset', dv.byteOffset, 0); 80 + 81 + const dv2 = new DataView(buffer, 4); 82 + test('DataView offset byteLength', dv2.byteLength, 12); 83 + test('DataView offset byteOffset', dv2.byteOffset, 4); 84 + 85 + const dv3 = new DataView(buffer, 4, 8); 86 + test('DataView offset+length byteLength', dv3.byteLength, 8); 87 + test('DataView offset+length byteOffset', dv3.byteOffset, 4); 88 + 89 + dv.setUint8(0, 42); 90 + test('DataView set/get Uint8', dv.getUint8(0), 42); 91 + 92 + dv.setUint8(0, 0x12); 93 + dv.setUint8(1, 0x34); 94 + test('DataView Int16 LE', dv.getInt16(0, true), 0x3412); 95 + test('DataView Int16 BE', dv.getInt16(0, false), 0x1234); 96 + 97 + const buf1 = Buffer.alloc(10); 98 + test('Buffer.alloc length', buf1.length, 10); 99 + 100 + const buf2 = Buffer.from('Hello'); 101 + test('Buffer.from string length', buf2.length, 5); 102 + test('Buffer.from string toString', buf2.toString(), 'Hello'); 103 + 104 + const buf3 = Buffer.from([72, 101, 108, 108, 111]); 105 + test('Buffer.from array length', buf3.length, 5); 106 + test('Buffer.from array toString', buf3.toString(), 'Hello'); 107 + 108 + const buf4 = Buffer.alloc(10); 109 + const written = buf4.write('Hello', 0); 110 + test('Buffer write bytes', written, 5); 111 + 112 + const buf5 = Buffer.from('Hello'); 113 + test('Buffer toString hex', buf5.toString('hex'), '48656c6c6f'); 114 + 115 + const original = new Uint8Array(10); 116 + const sliced = original.slice(2, 8); 117 + test('TypedArray slice length', sliced.length, 6); 118 + 119 + const subarrayed = original.subarray(2, 8); 120 + test('TypedArray subarray length', subarrayed.length, 6); 121 + test('TypedArray subarray byteOffset', subarrayed.byteOffset, 2); 122 + 123 + summary();
+154
examples/spec/classes.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Class Tests\n'); 4 + 5 + class Person { 6 + constructor(name, age) { 7 + this.name = name; 8 + this.age = age; 9 + } 10 + } 11 + 12 + let person = new Person('Alice', 30); 13 + test('constructor sets name', person.name, 'Alice'); 14 + test('constructor sets age', person.age, 30); 15 + 16 + class Calculator { 17 + constructor(value) { 18 + this.value = value; 19 + } 20 + add(n) { 21 + this.value = this.value + n; 22 + return this.value; 23 + } 24 + subtract(n) { 25 + this.value = this.value - n; 26 + return this.value; 27 + } 28 + } 29 + 30 + let calc = new Calculator(10); 31 + test('method add', calc.add(5), 15); 32 + test('method subtract', calc.subtract(3), 12); 33 + 34 + class Point { 35 + setCoords(x, y) { 36 + this.x = x; 37 + this.y = y; 38 + } 39 + getDistance() { 40 + return this.x * this.x + this.y * this.y; 41 + } 42 + } 43 + 44 + let p = new Point(); 45 + p.setCoords(3, 4); 46 + test('no constructor class', p.getDistance(), 25); 47 + 48 + class Counter { 49 + constructor(start) { 50 + this.count = start; 51 + } 52 + increment() { 53 + this.count = this.count + 1; 54 + return this.count; 55 + } 56 + } 57 + 58 + let c1 = new Counter(0); 59 + let c2 = new Counter(10); 60 + test('instance isolation c1', c1.increment(), 1); 61 + test('instance isolation c2', c2.increment(), 11); 62 + 63 + test('typeof instance', typeof person, 'object'); 64 + test('instanceof Object', person instanceof Object, true); 65 + 66 + class Rectangle { 67 + constructor(width, height) { 68 + this.width = width; 69 + this.height = height; 70 + } 71 + area() { 72 + return this.width * this.height; 73 + } 74 + } 75 + 76 + let rect = new Rectangle(5, 10); 77 + test('method uses props', rect.area(), 50); 78 + rect.width = 8; 79 + test('modified prop', rect.area(), 80); 80 + 81 + let p2 = new Person('Charlie', 35); 82 + delete p2.name; 83 + test('delete property', p2.name, undefined); 84 + test('other prop still exists', p2.age, 35); 85 + 86 + class Chainable { 87 + constructor(value) { 88 + this.value = value; 89 + } 90 + add(n) { 91 + this.value = this.value + n; 92 + return this; 93 + } 94 + multiply(n) { 95 + this.value = this.value * n; 96 + return this; 97 + } 98 + get() { 99 + return this.value; 100 + } 101 + } 102 + 103 + let chain = new Chainable(5); 104 + test('method chaining', chain.add(3).multiply(2).get(), 16); 105 + 106 + class Feature { 107 + constructor(name) { 108 + this.name = name; 109 + this.enabled = false; 110 + } 111 + enable() { 112 + this.enabled = true; 113 + } 114 + disable() { 115 + this.enabled = false; 116 + } 117 + } 118 + 119 + let feature = new Feature('DarkMode'); 120 + test('initial bool prop', feature.enabled, false); 121 + feature.enable(); 122 + test('toggle bool prop', feature.enabled, true); 123 + 124 + class Animal { 125 + constructor(name) { 126 + this.name = name; 127 + } 128 + speak() { 129 + return this.name + ' makes a sound'; 130 + } 131 + } 132 + 133 + class Dog extends Animal { 134 + speak() { 135 + return this.name + ' barks'; 136 + } 137 + } 138 + 139 + let dog = new Dog('Rex'); 140 + test('inheritance', dog.speak(), 'Rex barks'); 141 + test('instanceof parent', dog instanceof Animal, true); 142 + test('instanceof child', dog instanceof Dog, true); 143 + 144 + class Static { 145 + static value = 42; 146 + static method() { 147 + return 'static'; 148 + } 149 + } 150 + 151 + test('static property', Static.value, 42); 152 + test('static method', Static.method(), 'static'); 153 + 154 + summary();
+16
examples/spec/console.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Console Tests\n'); 4 + 5 + test('console.log exists', typeof console.log, 'function'); 6 + test('console.error exists', typeof console.error, 'function'); 7 + test('console.warn exists', typeof console.warn, 'function'); 8 + test('console.info exists', typeof console.info, 'function'); 9 + test('console.debug exists', typeof console.debug, 'function'); 10 + test('console.trace exists', typeof console.trace, 'function'); 11 + test('console.time exists', typeof console.time, 'function'); 12 + test('console.timeEnd exists', typeof console.timeEnd, 'function'); 13 + test('console.assert exists', typeof console.assert, 'function'); 14 + test('console.clear exists', typeof console.clear, 'function'); 15 + 16 + summary();
+38
examples/spec/date.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Date Tests\n'); 4 + 5 + const now1 = Date.now(); 6 + test('Date.now() is number', typeof now1, 'number'); 7 + test('Date.now() > 1970', now1 > 1000000000000, true); 8 + 9 + const d1 = new Date(); 10 + test('new Date() is object', typeof d1, 'object'); 11 + 12 + const d2 = new Date(1234567890000); 13 + test('new Date(ts) is object', typeof d2, 'object'); 14 + 15 + const t1 = Date.now(); 16 + const t2 = Date.now(); 17 + test('Date.now() is monotonic', t2 >= t1, true); 18 + 19 + const times = []; 20 + for (let i = 0; i < 3; i++) times.push(Date.now()); 21 + test('multiple calls are numbers', times.every(t => typeof t === 'number'), true); 22 + 23 + const d = new Date(1234567890000); 24 + test('getTime returns timestamp', d.getTime(), 1234567890000); 25 + test('getFullYear is number', typeof d.getFullYear(), 'number'); 26 + test('getMonth is number', typeof d.getMonth(), 'number'); 27 + test('getDate is number', typeof d.getDate(), 'number'); 28 + test('getHours is number', typeof d.getHours(), 'number'); 29 + test('getMinutes is number', typeof d.getMinutes(), 'number'); 30 + test('getSeconds is number', typeof d.getSeconds(), 'number'); 31 + test('getMilliseconds is number', typeof d.getMilliseconds(), 'number'); 32 + test('getDay is number', typeof d.getDay(), 'number'); 33 + 34 + test('toISOString is string', typeof d.toISOString(), 'string'); 35 + test('toISOString contains T', d.toISOString().includes('T'), true); 36 + test('toString is string', typeof d.toString(), 'string'); 37 + 38 + summary();
+54
examples/spec/destructuring.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Destructuring Tests\n'); 4 + 5 + const [a, b, c] = [1, 2, 3]; 6 + test('array destructure a', a, 1); 7 + test('array destructure b', b, 2); 8 + test('array destructure c', c, 3); 9 + 10 + const [first, , third] = [1, 2, 3]; 11 + test('skip element first', first, 1); 12 + test('skip element third', third, 3); 13 + 14 + const [x, y, z = 10] = [1, 2]; 15 + test('array default x', x, 1); 16 + test('array default z', z, 10); 17 + 18 + const [head, ...tail] = [1, 2, 3, 4]; 19 + test('array rest head', head, 1); 20 + testDeep('array rest tail', tail, [2, 3, 4]); 21 + 22 + const { name, age } = { name: 'Alice', age: 30 }; 23 + test('object destructure name', name, 'Alice'); 24 + test('object destructure age', age, 30); 25 + 26 + const { foo: renamed } = { foo: 'bar' }; 27 + test('object rename', renamed, 'bar'); 28 + 29 + const { val = 'default' } = {}; 30 + test('object default', val, 'default'); 31 + 32 + const { p, ...rest } = { p: 1, q: 2, r: 3 }; 33 + test('object rest p', p, 1); 34 + test('object rest has q', rest.q, 2); 35 + test('object rest has r', rest.r, 3); 36 + 37 + const nested = { outer: { inner: 42 } }; 38 + const { outer: { inner } } = nested; 39 + test('nested destructure', inner, 42); 40 + 41 + function destruct({ a, b }) { 42 + return a + b; 43 + } 44 + test('param destructure', destruct({ a: 3, b: 4 }), 7); 45 + 46 + function arrayParam([x, y]) { 47 + return x * y; 48 + } 49 + test('array param destructure', arrayParam([3, 4]), 12); 50 + 51 + const swap = ([a, b]) => [b, a]; 52 + testDeep('swap via destructure', swap([1, 2]), [2, 1]); 53 + 54 + summary();
+48
examples/spec/events.js
··· 1 + import { test, summary } from './helpers.js'; 2 + import { EventEmitter } from 'events'; 3 + 4 + console.log('EventEmitter Tests\n'); 5 + 6 + const ee = new EventEmitter(); 7 + 8 + let received = null; 9 + ee.on('test', (data) => { 10 + received = data; 11 + }); 12 + ee.emit('test', 'hello'); 13 + test('on and emit', received, 'hello'); 14 + 15 + let count = 0; 16 + ee.on('count', () => count++); 17 + ee.on('count', () => count++); 18 + ee.emit('count'); 19 + test('multiple listeners', count, 2); 20 + 21 + let onceValue = 0; 22 + ee.once('once', (val) => { 23 + onceValue = val; 24 + }); 25 + ee.emit('once', 42); 26 + ee.emit('once', 100); 27 + test('once only fires once', onceValue, 42); 28 + 29 + let removed = false; 30 + const handler = () => { removed = true; }; 31 + ee.on('remove', handler); 32 + ee.off('remove', handler); 33 + ee.emit('remove'); 34 + test('off removes listener', removed, false); 35 + 36 + let allRemoved = 0; 37 + ee.on('all', () => allRemoved++); 38 + ee.on('all', () => allRemoved++); 39 + ee.removeAllListeners('all'); 40 + ee.emit('all'); 41 + test('removeAllListeners', allRemoved, 0); 42 + 43 + test('listenerCount', ee.listenerCount('count'), 2); 44 + 45 + const names = ee.eventNames(); 46 + test('eventNames includes count', names.includes('count'), true); 47 + 48 + summary();
+120
examples/spec/exceptions.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Exception Tests\n'); 4 + 5 + let result1 = 'not caught'; 6 + try { 7 + throw new Error('test error'); 8 + result1 = 'should not reach'; 9 + } catch (e) { 10 + result1 = 'caught: ' + e.message; 11 + } 12 + test('basic try-catch', result1, 'caught: test error'); 13 + 14 + let result2 = 'initial'; 15 + try { 16 + result2 = 'no error'; 17 + } catch (e) { 18 + result2 = 'caught'; 19 + } 20 + test('try without exception', result2, 'no error'); 21 + 22 + let result3 = []; 23 + try { 24 + result3.push('try'); 25 + throw new Error('error'); 26 + } catch (e) { 27 + result3.push('catch'); 28 + } finally { 29 + result3.push('finally'); 30 + } 31 + testDeep('try-catch-finally', result3, ['try', 'catch', 'finally']); 32 + 33 + let result4 = []; 34 + try { 35 + result4.push('try'); 36 + } finally { 37 + result4.push('finally'); 38 + } 39 + testDeep('try-finally no error', result4, ['try', 'finally']); 40 + 41 + let result5 = 'not caught'; 42 + try { 43 + throw 'error string'; 44 + } catch { 45 + result5 = 'caught without binding'; 46 + } 47 + test('catch without binding', result5, 'caught without binding'); 48 + 49 + let result6 = []; 50 + try { 51 + result6.push('outer try'); 52 + try { 53 + result6.push('inner try'); 54 + throw new Error('inner error'); 55 + } catch (e) { 56 + result6.push('inner catch'); 57 + } 58 + result6.push('after inner'); 59 + } catch (e) { 60 + result6.push('outer catch'); 61 + } 62 + testDeep('nested try-catch', result6, ['outer try', 'inner try', 'inner catch', 'after inner']); 63 + 64 + let result7 = []; 65 + try { 66 + try { 67 + throw new Error('original'); 68 + } catch (e) { 69 + result7.push('first catch'); 70 + throw new Error('rethrown'); 71 + } 72 + } catch (e) { 73 + result7.push('second catch: ' + e.message); 74 + } 75 + testDeep('rethrow', result7, ['first catch', 'second catch: rethrown']); 76 + 77 + function testFinallyReturn() { 78 + let x = []; 79 + try { 80 + x.push('try'); 81 + return x; 82 + } finally { 83 + x.push('finally'); 84 + } 85 + } 86 + testDeep('finally with return', testFinallyReturn(), ['try', 'finally']); 87 + 88 + try { 89 + throw new Error('test message'); 90 + } catch (e) { 91 + test('error name', e.name, 'Error'); 92 + test('error message', e.message, 'test message'); 93 + } 94 + 95 + class CustomError extends Error { 96 + constructor(msg) { 97 + super(msg); 98 + this.name = 'CustomError'; 99 + } 100 + } 101 + 102 + try { 103 + throw new CustomError('custom message'); 104 + } catch (e) { 105 + test('custom error name', e.name, 'CustomError'); 106 + test('custom error message', e.message, 'custom message'); 107 + } 108 + 109 + let counter = 0; 110 + try { 111 + counter = 1; 112 + throw new Error('test'); 113 + } catch (e) { 114 + counter = 2; 115 + } finally { 116 + counter = counter + 10; 117 + } 118 + test('finally modifies value', counter, 12); 119 + 120 + summary();
+51
examples/spec/fs.js
··· 1 + import { test, summary } from './helpers.js'; 2 + import fs from 'fs'; 3 + import path from 'path'; 4 + 5 + console.log('FS Tests\n'); 6 + 7 + const testDir = '/tmp/ant-spec-test'; 8 + const testFile = path.join(testDir, 'test.txt'); 9 + 10 + fs.mkdirSync(testDir, { recursive: true }); 11 + test('mkdirSync creates dir', fs.existsSync(testDir), true); 12 + 13 + fs.writeFileSync(testFile, 'hello world'); 14 + test('writeFileSync creates file', fs.existsSync(testFile), true); 15 + 16 + const content = fs.readFileSync(testFile, 'utf8'); 17 + test('readFileSync content', content, 'hello world'); 18 + 19 + fs.appendFileSync(testFile, '!'); 20 + const appended = fs.readFileSync(testFile, 'utf8'); 21 + test('appendFileSync', appended, 'hello world!'); 22 + 23 + const stat = fs.statSync(testFile); 24 + test('statSync isFile', stat.isFile(), true); 25 + test('statSync isDirectory', stat.isDirectory(), false); 26 + test('statSync size', stat.size > 0, true); 27 + 28 + const dirStat = fs.statSync(testDir); 29 + test('statSync dir isDirectory', dirStat.isDirectory(), true); 30 + 31 + const copyFile = path.join(testDir, 'copy.txt'); 32 + fs.copyFileSync(testFile, copyFile); 33 + test('copyFileSync', fs.existsSync(copyFile), true); 34 + 35 + const renameFile = path.join(testDir, 'renamed.txt'); 36 + fs.renameSync(copyFile, renameFile); 37 + test('renameSync', fs.existsSync(renameFile), true); 38 + test('renameSync removes old', fs.existsSync(copyFile), false); 39 + 40 + const files = fs.readdirSync(testDir); 41 + test('readdirSync length', files.length >= 2, true); 42 + test('readdirSync includes test.txt', files.includes('test.txt'), true); 43 + 44 + fs.unlinkSync(testFile); 45 + test('unlinkSync removes file', fs.existsSync(testFile), false); 46 + 47 + fs.unlinkSync(renameFile); 48 + fs.rmdirSync(testDir); 49 + test('rmdirSync removes dir', fs.existsSync(testDir), false); 50 + 51 + summary();
+106
examples/spec/functions.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Function Tests\n'); 4 + 5 + function add(a, b) { 6 + return a + b; 7 + } 8 + test('function declaration', add(2, 3), 5); 9 + 10 + const multiply = function(a, b) { 11 + return a * b; 12 + }; 13 + test('function expression', multiply(3, 4), 12); 14 + 15 + const arrow = (a, b) => a - b; 16 + test('arrow function', arrow(10, 3), 7); 17 + 18 + const arrowSingle = x => x * 2; 19 + test('arrow single param', arrowSingle(5), 10); 20 + 21 + const arrowBlock = (a, b) => { 22 + const sum = a + b; 23 + return sum * 2; 24 + }; 25 + test('arrow block body', arrowBlock(2, 3), 10); 26 + 27 + function defaultParam(a, b = 10) { 28 + return a + b; 29 + } 30 + test('default param used', defaultParam(5), 15); 31 + test('default param overridden', defaultParam(5, 3), 8); 32 + 33 + function restParams(first, ...rest) { 34 + return first + rest.length; 35 + } 36 + test('rest params', restParams(1, 2, 3, 4), 4); 37 + 38 + function spreadCall(a, b, c) { 39 + return a + b + c; 40 + } 41 + test('spread in call', spreadCall(...[1, 2, 3]), 6); 42 + 43 + const obj = { 44 + value: 100, 45 + getValue() { 46 + return this.value; 47 + } 48 + }; 49 + test('method this', obj.getValue(), 100); 50 + 51 + const arrowThis = { 52 + value: 50, 53 + getArrow() { 54 + return (() => this.value)(); 55 + } 56 + }; 57 + test('arrow this binding', arrowThis.getArrow(), 50); 58 + 59 + function outer() { 60 + let x = 10; 61 + return function inner() { 62 + return x; 63 + }; 64 + } 65 + test('closure', outer()(), 10); 66 + 67 + const counter = (() => { 68 + let count = 0; 69 + return { 70 + inc() { return ++count; }, 71 + get() { return count; } 72 + }; 73 + })(); 74 + test('iife closure inc', counter.inc(), 1); 75 + test('iife closure get', counter.get(), 1); 76 + 77 + function factorial(n) { 78 + if (n <= 1) return 1; 79 + return n * factorial(n - 1); 80 + } 81 + test('recursion', factorial(5), 120); 82 + 83 + test('function name', add.name, 'add'); 84 + test('function length', add.length, 2); 85 + 86 + function bindTest(greeting) { 87 + return greeting + ' ' + this.name; 88 + } 89 + const boundFn = bindTest.bind({ name: 'World' }); 90 + test('bind', boundFn('Hello'), 'Hello World'); 91 + 92 + test('call', bindTest.call({ name: 'Call' }, 'Hi'), 'Hi Call'); 93 + test('apply', bindTest.apply({ name: 'Apply' }, ['Hey']), 'Hey Apply'); 94 + 95 + const gen = (function() { 96 + const fns = []; 97 + for (let i = 0; i < 3; i++) { 98 + fns.push(() => i); 99 + } 100 + return fns; 101 + })(); 102 + test('closure in loop 0', gen[0](), 0); 103 + test('closure in loop 1', gen[1](), 1); 104 + test('closure in loop 2', gen[2](), 2); 105 + 106 + summary();
+60
examples/spec/generators.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Generator Tests\n'); 4 + 5 + function* simple() { 6 + yield 1; 7 + yield 2; 8 + yield 3; 9 + } 10 + 11 + const gen = simple(); 12 + test('first yield', gen.next().value, 1); 13 + test('second yield', gen.next().value, 2); 14 + test('third yield', gen.next().value, 3); 15 + test('done', gen.next().done, true); 16 + 17 + function* withReturn() { 18 + yield 1; 19 + return 'final'; 20 + } 21 + 22 + const gen2 = withReturn(); 23 + test('yield before return', gen2.next().value, 1); 24 + const last = gen2.next(); 25 + test('return value', last.value, 'final'); 26 + test('return done', last.done, true); 27 + 28 + function* counter(start) { 29 + let i = start; 30 + while (true) { 31 + yield i++; 32 + } 33 + } 34 + 35 + const c = counter(10); 36 + test('counter 10', c.next().value, 10); 37 + test('counter 11', c.next().value, 11); 38 + test('counter 12', c.next().value, 12); 39 + 40 + function* range(start, end) { 41 + for (let i = start; i <= end; i++) { 42 + yield i; 43 + } 44 + } 45 + 46 + const arr = [...range(1, 5)]; 47 + testDeep('spread generator', arr, [1, 2, 3, 4, 5]); 48 + 49 + function* twoWay() { 50 + const x = yield 1; 51 + const y = yield x + 1; 52 + yield y + 1; 53 + } 54 + 55 + const tw = twoWay(); 56 + test('two way first', tw.next().value, 1); 57 + test('two way second', tw.next(10).value, 11); 58 + test('two way third', tw.next(20).value, 21); 59 + 60 + summary();
+22
examples/spec/globalthis.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('GlobalThis Tests\n'); 4 + 5 + test('globalThis exists', typeof globalThis, 'object'); 6 + test('globalThis.console', typeof globalThis.console, 'object'); 7 + test('globalThis.setTimeout', typeof globalThis.setTimeout, 'function'); 8 + test('globalThis.Object', globalThis.Object === Object, true); 9 + test('globalThis.Array', globalThis.Array === Array, true); 10 + test('globalThis.Math', globalThis.Math === Math, true); 11 + test('globalThis.JSON', globalThis.JSON === JSON, true); 12 + 13 + globalThis.testGlobal = 42; 14 + test('set on globalThis', testGlobal, 42); 15 + 16 + test('process exists', typeof process, 'object'); 17 + test('process.env exists', typeof process.env, 'object'); 18 + test('process.argv exists', typeof process.argv, 'object'); 19 + test('process.exit exists', typeof process.exit, 'function'); 20 + test('process.cwd exists', typeof process.cwd, 'function'); 21 + 22 + summary();
+63
examples/spec/helpers.js
··· 1 + const GREEN = '\x1b[32m'; 2 + const RED = '\x1b[31m'; 3 + const RESET = '\x1b[0m'; 4 + 5 + let passed = 0; 6 + let failed = 0; 7 + 8 + export function test(name, actual, expected) { 9 + if (actual === expected) { 10 + console.log(`${GREEN}โœ“${RESET} ${name}`); 11 + passed++; 12 + } else { 13 + console.log(`${RED}โœ—${RESET} ${name}`); 14 + console.log(` Expected: ${expected}`); 15 + console.log(` Actual: ${actual}`); 16 + failed++; 17 + } 18 + } 19 + 20 + export function testApprox(name, actual, expected, epsilon = 1e-10) { 21 + const pass = (Number.isNaN(actual) && Number.isNaN(expected)) || 22 + (!Number.isFinite(actual) && !Number.isFinite(expected) && actual === expected) || 23 + Math.abs(actual - expected) < epsilon; 24 + if (pass) { 25 + console.log(`${GREEN}โœ“${RESET} ${name}`); 26 + passed++; 27 + } else { 28 + console.log(`${RED}โœ—${RESET} ${name}`); 29 + console.log(` Expected: ${expected}`); 30 + console.log(` Actual: ${actual}`); 31 + failed++; 32 + } 33 + } 34 + 35 + export function testThrows(name, fn) { 36 + try { 37 + fn(); 38 + console.log(`${RED}โœ—${RESET} ${name} (expected to throw)`); 39 + failed++; 40 + } catch (e) { 41 + console.log(`${GREEN}โœ“${RESET} ${name}`); 42 + passed++; 43 + } 44 + } 45 + 46 + export function testDeep(name, actual, expected) { 47 + const pass = JSON.stringify(actual) === JSON.stringify(expected); 48 + if (pass) { 49 + console.log(`${GREEN}โœ“${RESET} ${name}`); 50 + passed++; 51 + } else { 52 + console.log(`${RED}โœ—${RESET} ${name}`); 53 + console.log(` Expected: ${JSON.stringify(expected)}`); 54 + console.log(` Actual: ${JSON.stringify(actual)}`); 55 + failed++; 56 + } 57 + } 58 + 59 + export function summary() { 60 + console.log(`\nPassed: ${passed}`); 61 + console.log(`Failed: ${failed}`); 62 + if (failed > 0) process.exit(1); 63 + }
+62
examples/spec/iterators.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Iterator Tests\n'); 4 + 5 + const arr = [1, 2, 3]; 6 + const iter = arr[Symbol.iterator](); 7 + test('array iterator first', iter.next().value, 1); 8 + test('array iterator second', iter.next().value, 2); 9 + test('array iterator third', iter.next().value, 3); 10 + test('array iterator done', iter.next().done, true); 11 + 12 + const str = 'abc'; 13 + const strIter = str[Symbol.iterator](); 14 + test('string iterator first', strIter.next().value, 'a'); 15 + test('string iterator second', strIter.next().value, 'b'); 16 + test('string iterator third', strIter.next().value, 'c'); 17 + test('string iterator done', strIter.next().done, true); 18 + 19 + const map = new Map([['a', 1], ['b', 2]]); 20 + const mapIter = map.entries(); 21 + testDeep('map entries first', mapIter.next().value, ['a', 1]); 22 + testDeep('map entries second', mapIter.next().value, ['b', 2]); 23 + 24 + const set = new Set([1, 2, 3]); 25 + const setIter = set.values(); 26 + test('set values first', setIter.next().value, 1); 27 + test('set values second', setIter.next().value, 2); 28 + 29 + let forOfSum = 0; 30 + for (const n of [1, 2, 3]) { 31 + forOfSum += n; 32 + } 33 + test('for-of array', forOfSum, 6); 34 + 35 + let forOfStr = ''; 36 + for (const c of 'hi') { 37 + forOfStr += c; 38 + } 39 + test('for-of string', forOfStr, 'hi'); 40 + 41 + const custom = { 42 + data: [10, 20, 30], 43 + [Symbol.iterator]() { 44 + let i = 0; 45 + return { 46 + next: () => { 47 + if (i < this.data.length) { 48 + return { value: this.data[i++], done: false }; 49 + } 50 + return { done: true }; 51 + } 52 + }; 53 + } 54 + }; 55 + 56 + let customSum = 0; 57 + for (const n of custom) { 58 + customSum += n; 59 + } 60 + test('custom iterator', customSum, 60); 61 + 62 + summary();
+73
examples/spec/json.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('JSON Tests\n'); 4 + 5 + let obj1 = JSON.parse('{"name":"John","age":30}'); 6 + test('parse object name', obj1.name, 'John'); 7 + test('parse object age', obj1.age, 30); 8 + 9 + let arr = JSON.parse('[1,2,3,4,5]'); 10 + test('parse array length', arr.length, 5); 11 + test('parse array first', arr[0], 1); 12 + test('parse array last', arr[4], 5); 13 + 14 + let nested = JSON.parse('{"user":{"name":"Alice","age":25},"active":true}'); 15 + test('parse nested name', nested.user.name, 'Alice'); 16 + test('parse nested age', nested.user.age, 25); 17 + test('parse nested bool', nested.active, true); 18 + 19 + let arrObj = JSON.parse('[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"}]'); 20 + test('parse array of objects length', arrObj.length, 2); 21 + test('parse array of objects first name', arrObj[0].name, 'Item1'); 22 + test('parse array of objects second id', arrObj[1].id, 2); 23 + 24 + let types = JSON.parse('{"active":true,"inactive":false,"data":null,"count":123}'); 25 + test('parse bool true', types.active, true); 26 + test('parse bool false', types.inactive, false); 27 + test('parse null', types.data, null); 28 + test('parse number', types.count, 123); 29 + 30 + let nums = JSON.parse('{"int":42,"float":3.14,"negative":-10,"zero":0}'); 31 + test('parse int', nums.int, 42); 32 + test('parse float', nums.float, 3.14); 33 + test('parse negative', nums.negative, -10); 34 + test('parse zero', nums.zero, 0); 35 + 36 + let emptyObj = JSON.parse('{}'); 37 + let emptyArr = JSON.parse('[]'); 38 + testDeep('parse empty object', emptyObj, {}); 39 + test('parse empty array length', emptyArr.length, 0); 40 + 41 + let stringified = JSON.stringify([10, 20, 30]); 42 + test('stringify array', stringified, '[10,20,30]'); 43 + 44 + let objStr = JSON.stringify({ name: 'Charlie', age: 35 }); 45 + test('stringify object contains name', objStr.includes('"name"'), true); 46 + test('stringify object contains age', objStr.includes('"age"'), true); 47 + 48 + let withTypes = JSON.stringify({ active: true, inactive: false, data: null }); 49 + test('stringify bool true', withTypes.includes('true'), true); 50 + test('stringify bool false', withTypes.includes('false'), true); 51 + test('stringify null', withTypes.includes('null'), true); 52 + 53 + let original = '{"count":5}'; 54 + let parsed = JSON.parse(original); 55 + parsed.count = 10; 56 + test('modify after parse', parsed.count, 10); 57 + 58 + let spacedJson = ' { "key" : "value" } '; 59 + let spacedParsed = JSON.parse(spacedJson); 60 + test('parse with whitespace', spacedParsed.key, 'value'); 61 + 62 + let api = JSON.parse('{"status":"success","data":{"user":"john","token":"abc123"}}'); 63 + test('parse api status', api.status, 'success'); 64 + test('parse api data user', api.data.user, 'john'); 65 + test('parse api data token', api.data.token, 'abc123'); 66 + 67 + let roundtrip = { a: 1, b: 'two', c: true }; 68 + let rt = JSON.parse(JSON.stringify(roundtrip)); 69 + test('roundtrip a', rt.a, 1); 70 + test('roundtrip b', rt.b, 'two'); 71 + test('roundtrip c', rt.c, true); 72 + 73 + summary();
+93
examples/spec/loops.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Loop Tests\n'); 4 + 5 + let sum = 0; 6 + for (let i = 0; i < 5; i++) sum += i; 7 + test('for loop sum', sum, 10); 8 + 9 + let nested = 0; 10 + for (let i = 0; i < 3; i++) { 11 + for (let j = 0; j < 3; j++) { 12 + nested++; 13 + } 14 + } 15 + test('nested for loops', nested, 9); 16 + 17 + function findFirst(arr, target) { 18 + for (let i = 0; i < arr.length; i++) { 19 + if (arr[i] === target) return i; 20 + } 21 + return -1; 22 + } 23 + test('for loop return', findFirst([10, 20, 30], 20), 1); 24 + test('for loop return not found', findFirst([10, 20, 30], 99), -1); 25 + 26 + let breakSum = 0; 27 + for (let i = 0; i < 10; i++) { 28 + if (i === 5) break; 29 + breakSum += i; 30 + } 31 + test('for loop break', breakSum, 10); 32 + 33 + let evenSum = 0; 34 + for (let i = 0; i < 10; i++) { 35 + if (i % 2 === 1) continue; 36 + evenSum += i; 37 + } 38 + test('for loop continue', evenSum, 20); 39 + 40 + let k = 0; 41 + let extCount = 0; 42 + for (; k < 5; k++) extCount++; 43 + test('for loop external init', extCount, 5); 44 + 45 + let countdown = 0; 46 + for (let i = 5; i > 0; i--) countdown += i; 47 + test('for loop decrement', countdown, 15); 48 + 49 + let arr = [1, 2, 3, 4, 5]; 50 + for (let i = 0; i < arr.length; i++) arr[i] *= 2; 51 + testDeep('for loop modify array', arr, [2, 4, 6, 8, 10]); 52 + 53 + let str = 'hello'; 54 + let chars = ''; 55 + for (let i = 0; i < str.length; i++) chars += str[i]; 56 + test('for loop string', chars, 'hello'); 57 + 58 + let whileSum = 0; 59 + let j = 0; 60 + while (j < 5) { 61 + whileSum += j; 62 + j++; 63 + } 64 + test('while loop', whileSum, 10); 65 + 66 + let doSum = 0; 67 + let d = 0; 68 + do { 69 + doSum += d; 70 + d++; 71 + } while (d < 5); 72 + test('do-while loop', doSum, 10); 73 + 74 + const obj = { a: 1, b: 2, c: 3 }; 75 + let keys = []; 76 + for (let key in obj) keys.push(key); 77 + test('for-in keys length', keys.length, 3); 78 + test('for-in has a', keys.includes('a'), true); 79 + 80 + const items = [10, 20, 30]; 81 + let forOfSum = 0; 82 + for (let item of items) forOfSum += item; 83 + test('for-of sum', forOfSum, 60); 84 + 85 + let forOfChars = ''; 86 + for (let c of 'abc') forOfChars += c; 87 + test('for-of string', forOfChars, 'abc'); 88 + 89 + let largeSum = 0; 90 + for (let i = 0; i < 1000; i++) largeSum += i; 91 + test('large loop', largeSum, 499500); 92 + 93 + summary();
+47
examples/spec/map.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Map Tests\n'); 4 + 5 + const map = new Map(); 6 + 7 + map.set('key1', 'value1'); 8 + map.set('key2', 42); 9 + map.set('key3', true); 10 + 11 + test('map size after set', map.size(), 3); 12 + test('map get string', map.get('key1'), 'value1'); 13 + test('map get number', map.get('key2'), 42); 14 + test('map get boolean', map.get('key3'), true); 15 + 16 + test('map has existing', map.has('key1'), true); 17 + test('map has missing', map.has('missing'), false); 18 + 19 + test('map delete returns true', map.delete('key2'), true); 20 + test('map has after delete', map.has('key2'), false); 21 + test('map size after delete', map.size(), 2); 22 + 23 + map.set('key1', 'newvalue1'); 24 + test('map get after overwrite', map.get('key1'), 'newvalue1'); 25 + 26 + map.clear(); 27 + test('map size after clear', map.size(), 0); 28 + test('map has after clear', map.has('key1'), false); 29 + 30 + map.set(123, 'number key'); 31 + map.set(true, 'boolean key'); 32 + map.set(null, 'null key'); 33 + 34 + test('map get number key', map.get(123), 'number key'); 35 + test('map get boolean key', map.get(true), 'boolean key'); 36 + test('map get null key', map.get(null), 'null key'); 37 + test('map size with varied keys', map.size(), 3); 38 + 39 + map.clear(); 40 + map.set('a', 1).set('b', 2).set('c', 3); 41 + test('map chaining size', map.size(), 3); 42 + test('map chaining get', map.get('b'), 2); 43 + 44 + test('map get undefined key', map.get('nonexistent'), undefined); 45 + test('map delete nonexistent', map.delete('nonexistent'), false); 46 + 47 + summary();
+123
examples/spec/math.js
··· 1 + import { test, testApprox, summary } from './helpers.js'; 2 + 3 + console.log('Math Tests\n'); 4 + 5 + testApprox('Math.E', Math.E, 2.718281828459045); 6 + testApprox('Math.PI', Math.PI, 3.141592653589793); 7 + testApprox('Math.LN10', Math.LN10, 2.302585092994046); 8 + testApprox('Math.LN2', Math.LN2, 0.6931471805599453); 9 + testApprox('Math.LOG10E', Math.LOG10E, 0.4342944819032518); 10 + testApprox('Math.LOG2E', Math.LOG2E, 1.4426950408889634); 11 + testApprox('Math.SQRT2', Math.SQRT2, 1.4142135623730951); 12 + testApprox('Math.SQRT1_2', Math.SQRT1_2, 0.7071067811865476); 13 + 14 + test('Math.abs(5)', Math.abs(5), 5); 15 + test('Math.abs(-5)', Math.abs(-5), 5); 16 + test('Math.abs(0)', Math.abs(0), 0); 17 + 18 + testApprox('Math.acos(1)', Math.acos(1), 0); 19 + testApprox('Math.acos(0)', Math.acos(0), Math.PI / 2); 20 + testApprox('Math.acos(-1)', Math.acos(-1), Math.PI); 21 + test('Math.acos(2) is NaN', Number.isNaN(Math.acos(2)), true); 22 + 23 + testApprox('Math.asin(0)', Math.asin(0), 0); 24 + testApprox('Math.asin(1)', Math.asin(1), Math.PI / 2); 25 + 26 + testApprox('Math.atan(0)', Math.atan(0), 0); 27 + testApprox('Math.atan(1)', Math.atan(1), Math.PI / 4); 28 + 29 + testApprox('Math.atan2(1, 1)', Math.atan2(1, 1), Math.PI / 4); 30 + testApprox('Math.atan2(1, 0)', Math.atan2(1, 0), Math.PI / 2); 31 + 32 + testApprox('Math.cbrt(8)', Math.cbrt(8), 2); 33 + testApprox('Math.cbrt(-8)', Math.cbrt(-8), -2); 34 + testApprox('Math.cbrt(27)', Math.cbrt(27), 3); 35 + 36 + test('Math.ceil(0.5)', Math.ceil(0.5), 1); 37 + test('Math.ceil(-0.5)', Math.ceil(-0.5), 0); 38 + test('Math.ceil(4.7)', Math.ceil(4.7), 5); 39 + 40 + test('Math.floor(0.5)', Math.floor(0.5), 0); 41 + test('Math.floor(-0.5)', Math.floor(-0.5), -1); 42 + test('Math.floor(4.7)', Math.floor(4.7), 4); 43 + 44 + test('Math.round(0.5)', Math.round(0.5), 1); 45 + test('Math.round(0.49)', Math.round(0.49), 0); 46 + test('Math.round(4.7)', Math.round(4.7), 5); 47 + 48 + test('Math.trunc(4.7)', Math.trunc(4.7), 4); 49 + test('Math.trunc(-4.7)', Math.trunc(-4.7), -4); 50 + 51 + testApprox('Math.cos(0)', Math.cos(0), 1); 52 + testApprox('Math.cos(Math.PI)', Math.cos(Math.PI), -1); 53 + 54 + testApprox('Math.sin(0)', Math.sin(0), 0); 55 + testApprox('Math.sin(Math.PI/2)', Math.sin(Math.PI / 2), 1); 56 + 57 + testApprox('Math.tan(0)', Math.tan(0), 0); 58 + testApprox('Math.tan(Math.PI/4)', Math.tan(Math.PI / 4), 1); 59 + 60 + testApprox('Math.exp(0)', Math.exp(0), 1); 61 + testApprox('Math.exp(1)', Math.exp(1), Math.E); 62 + 63 + testApprox('Math.log(1)', Math.log(1), 0); 64 + testApprox('Math.log(Math.E)', Math.log(Math.E), 1); 65 + 66 + testApprox('Math.log10(1)', Math.log10(1), 0); 67 + testApprox('Math.log10(10)', Math.log10(10), 1); 68 + testApprox('Math.log10(100)', Math.log10(100), 2); 69 + 70 + testApprox('Math.log2(1)', Math.log2(1), 0); 71 + testApprox('Math.log2(2)', Math.log2(2), 1); 72 + testApprox('Math.log2(8)', Math.log2(8), 3); 73 + 74 + test('Math.max(1, 2, 3)', Math.max(1, 2, 3), 3); 75 + test('Math.max(-1, -2, -3)', Math.max(-1, -2, -3), -1); 76 + test('Math.max()', Math.max(), -Infinity); 77 + 78 + test('Math.min(1, 2, 3)', Math.min(1, 2, 3), 1); 79 + test('Math.min(-1, -2, -3)', Math.min(-1, -2, -3), -3); 80 + test('Math.min()', Math.min(), Infinity); 81 + 82 + test('Math.pow(2, 3)', Math.pow(2, 3), 8); 83 + test('Math.pow(2, 10)', Math.pow(2, 10), 1024); 84 + test('Math.pow(10, 0)', Math.pow(10, 0), 1); 85 + testApprox('Math.pow(4, 0.5)', Math.pow(4, 0.5), 2); 86 + 87 + let r = Math.random(); 88 + test('Math.random() >= 0', r >= 0, true); 89 + test('Math.random() < 1', r < 1, true); 90 + 91 + test('Math.sign(5)', Math.sign(5), 1); 92 + test('Math.sign(-5)', Math.sign(-5), -1); 93 + test('Math.sign(0)', Math.sign(0), 0); 94 + 95 + testApprox('Math.sqrt(4)', Math.sqrt(4), 2); 96 + testApprox('Math.sqrt(9)', Math.sqrt(9), 3); 97 + test('Math.sqrt(-1) is NaN', Number.isNaN(Math.sqrt(-1)), true); 98 + 99 + testApprox('Math.hypot(3, 4)', Math.hypot(3, 4), 5); 100 + testApprox('Math.hypot(5, 12)', Math.hypot(5, 12), 13); 101 + 102 + test('Math.clz32(1)', Math.clz32(1), 31); 103 + test('Math.clz32(0)', Math.clz32(0), 32); 104 + 105 + test('Math.imul(2, 4)', Math.imul(2, 4), 8); 106 + test('Math.imul(-1, 8)', Math.imul(-1, 8), -8); 107 + 108 + testApprox('Math.cosh(0)', Math.cosh(0), 1); 109 + testApprox('Math.sinh(0)', Math.sinh(0), 0); 110 + testApprox('Math.tanh(0)', Math.tanh(0), 0); 111 + 112 + testApprox('Math.acosh(1)', Math.acosh(1), 0); 113 + testApprox('Math.asinh(0)', Math.asinh(0), 0); 114 + testApprox('Math.atanh(0)', Math.atanh(0), 0); 115 + 116 + testApprox('Math.expm1(0)', Math.expm1(0), 0); 117 + testApprox('Math.log1p(0)', Math.log1p(0), 0); 118 + 119 + test('Math.abs(NaN) is NaN', Number.isNaN(Math.abs(NaN)), true); 120 + test('Math.abs(-Infinity)', Math.abs(-Infinity), Infinity); 121 + test('Math.log(0)', Math.log(0), -Infinity); 122 + 123 + summary();
+12
examples/spec/modules.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Module Tests\n'); 4 + 5 + test('import.meta exists', typeof import.meta, 'object'); 6 + test('import.meta.url exists', typeof import.meta.url, 'string'); 7 + test('import.meta.url is file', import.meta.url.startsWith('file://'), true); 8 + 9 + test('module imported test', typeof test, 'function'); 10 + test('module imported summary', typeof summary, 'function'); 11 + 12 + summary();
+69
examples/spec/numbers.js
··· 1 + import { test, testApprox, summary } from './helpers.js'; 2 + 3 + console.log('Number Tests\n'); 4 + 5 + test('integer literal', 42, 42); 6 + test('float literal', 3.14, 3.14); 7 + test('negative number', -5, -5); 8 + test('zero', 0, 0); 9 + 10 + test('hex literal', 0xff, 255); 11 + test('octal literal', 0o77, 63); 12 + test('binary literal', 0b1010, 10); 13 + 14 + test('exponential', 1e3, 1000); 15 + test('exponential negative', 1e-3, 0.001); 16 + 17 + test('numeric separator', 1_000_000, 1000000); 18 + 19 + test('Number()', Number('42'), 42); 20 + test('Number() float', Number('3.14'), 3.14); 21 + test('Number() invalid', Number.isNaN(Number('abc')), true); 22 + 23 + test('parseInt', parseInt('42'), 42); 24 + test('parseInt radix', parseInt('ff', 16), 255); 25 + test('parseFloat', parseFloat('3.14'), 3.14); 26 + 27 + test('Number.isInteger true', Number.isInteger(5), true); 28 + test('Number.isInteger false', Number.isInteger(5.5), false); 29 + 30 + test('Number.isFinite true', Number.isFinite(100), true); 31 + test('Number.isFinite false', Number.isFinite(Infinity), false); 32 + 33 + test('Number.isNaN true', Number.isNaN(NaN), true); 34 + test('Number.isNaN false', Number.isNaN(5), false); 35 + 36 + test('isNaN coercing', isNaN('abc'), true); 37 + test('Number.isNaN strict', Number.isNaN('abc'), false); 38 + 39 + test('Infinity', Infinity > 1e308, true); 40 + test('-Infinity', -Infinity < -1e308, true); 41 + 42 + test('NaN !== NaN', NaN !== NaN, true); 43 + 44 + test('Number.MAX_VALUE', Number.MAX_VALUE > 1e308, true); 45 + test('Number.MIN_VALUE', Number.MIN_VALUE > 0, true); 46 + test('Number.MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER, 9007199254740991); 47 + test('Number.MIN_SAFE_INTEGER', Number.MIN_SAFE_INTEGER, -9007199254740991); 48 + 49 + test('Number.isSafeInteger true', Number.isSafeInteger(42), true); 50 + test('Number.isSafeInteger false', Number.isSafeInteger(9007199254740992), false); 51 + 52 + test('toFixed', (3.14159).toFixed(2), '3.14'); 53 + test('toPrecision', (123.456).toPrecision(4), '123.5'); 54 + test('toExponential', (12345).toExponential(2), '1.23e+4'); 55 + test('toString', (255).toString(16), 'ff'); 56 + 57 + testApprox('addition', 0.1 + 0.2, 0.3, 1e-10); 58 + test('multiplication', 6 * 7, 42); 59 + test('division', 10 / 4, 2.5); 60 + test('modulo', 17 % 5, 2); 61 + test('exponentiation', 2 ** 10, 1024); 62 + 63 + test('unary plus', +'42', 42); 64 + test('unary minus', -42, -42); 65 + 66 + test('Math.floor division', Math.floor(7 / 2), 3); 67 + test('bitwise or floor', 7 / 2 | 0, 3); 68 + 69 + summary();
+80
examples/spec/objects.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Object Tests\n'); 4 + 5 + let obj = { a: 1, b: 2, c: 3 }; 6 + test('object property access', obj.a, 1); 7 + test('object bracket access', obj['b'], 2); 8 + test('object property count', Object.keys(obj).length, 3); 9 + 10 + obj.d = 4; 11 + test('add property', obj.d, 4); 12 + 13 + obj.a = 10; 14 + test('modify property', obj.a, 10); 15 + 16 + delete obj.d; 17 + test('delete property', obj.d, undefined); 18 + 19 + test('in operator true', 'a' in obj, true); 20 + test('in operator false', 'z' in obj, false); 21 + 22 + testDeep('Object.keys', Object.keys({ x: 1, y: 2 }), ['x', 'y']); 23 + testDeep('Object.values', Object.values({ x: 1, y: 2 }), [1, 2]); 24 + testDeep('Object.entries', Object.entries({ x: 1 }), [['x', 1]]); 25 + 26 + let merged = Object.assign({}, { a: 1 }, { b: 2 }); 27 + test('Object.assign a', merged.a, 1); 28 + test('Object.assign b', merged.b, 2); 29 + 30 + let nested = { a: { b: { c: 1 } } }; 31 + test('nested access', nested.a.b.c, 1); 32 + 33 + let computed = { ['key' + 1]: 'value' }; 34 + test('computed property', computed.key1, 'value'); 35 + 36 + let short = 'hello'; 37 + let shorthand = { short }; 38 + test('shorthand property', shorthand.short, 'hello'); 39 + 40 + let methodObj = { 41 + value: 42, 42 + getValue() { 43 + return this.value; 44 + } 45 + }; 46 + test('method shorthand', methodObj.getValue(), 42); 47 + 48 + let source = { a: 1, b: 2 }; 49 + let spread = { ...source, c: 3 }; 50 + test('spread a', spread.a, 1); 51 + test('spread c', spread.c, 3); 52 + 53 + let { a, b } = { a: 1, b: 2, c: 3 }; 54 + test('destructuring a', a, 1); 55 + test('destructuring b', b, 2); 56 + 57 + let { x: renamed } = { x: 5 }; 58 + test('destructuring rename', renamed, 5); 59 + 60 + let { y = 10 } = {}; 61 + test('destructuring default', y, 10); 62 + 63 + test('hasOwnProperty true', ({ a: 1 }).hasOwnProperty('a'), true); 64 + test('hasOwnProperty false', ({ a: 1 }).hasOwnProperty('b'), false); 65 + 66 + let frozen = Object.freeze({ a: 1 }); 67 + test('Object.isFrozen', Object.isFrozen(frozen), true); 68 + 69 + let sealed = Object.seal({ a: 1 }); 70 + test('Object.isSealed', Object.isSealed(sealed), true); 71 + 72 + let proto = { inherited: true }; 73 + let child = Object.create(proto); 74 + test('Object.create inherits', child.inherited, true); 75 + 76 + test('Object.getPrototypeOf', Object.getPrototypeOf([]) === Array.prototype, true); 77 + 78 + testDeep('Object.fromEntries', Object.fromEntries([['a', 1], ['b', 2]]), { a: 1, b: 2 }); 79 + 80 + summary();
+115
examples/spec/operators.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Operator Tests\n'); 4 + 5 + test('5 == 5', 5 == 5, true); 6 + test('5 === 5', 5 === 5, true); 7 + test('5 != 10', 5 != 10, true); 8 + test('5 !== 10', 5 !== 10, true); 9 + test('5 == 10', 5 == 10, false); 10 + test('5 != 5', 5 != 5, false); 11 + 12 + test("'hello' == 'hello'", 'hello' == 'hello', true); 13 + test("'hello' === 'hello'", 'hello' === 'hello', true); 14 + test("'hello' != 'world'", 'hello' != 'world', true); 15 + test("'hello' == 'world'", 'hello' == 'world', false); 16 + 17 + test('true == true', true == true, true); 18 + test('true === true', true === true, true); 19 + test('true != false', true != false, true); 20 + test('false == false', false == false, true); 21 + 22 + test('undefined == undefined', undefined == undefined, true); 23 + test('undefined === undefined', undefined === undefined, true); 24 + test('null == null', null == null, true); 25 + test('null === null', null === null, true); 26 + test('undefined == null', undefined == null, true); 27 + test('undefined === null', undefined === null, false); 28 + 29 + test('5 !== "5"', 5 !== '5', true); 30 + test('true !== 1', true !== 1, true); 31 + 32 + let obj1 = { x: 1 }; 33 + let obj2 = { x: 1 }; 34 + let obj3 = obj1; 35 + test('obj1 == obj2 (diff refs)', obj1 == obj2, false); 36 + test('obj1 === obj3 (same ref)', obj1 === obj3, true); 37 + 38 + let arr1 = [1, 2, 3]; 39 + let arr2 = [1, 2, 3]; 40 + let arr3 = arr1; 41 + test('arr1 == arr2 (diff refs)', arr1 == arr2, false); 42 + test('arr1 === arr3 (same ref)', arr1 === arr3, true); 43 + 44 + test('5 > 3', 5 > 3, true); 45 + test('3 < 5', 3 < 5, true); 46 + test('5 >= 5', 5 >= 5, true); 47 + test('5 <= 5', 5 <= 5, true); 48 + test('5 > 5', 5 > 5, false); 49 + test('5 < 5', 5 < 5, false); 50 + 51 + test('2 + 3', 2 + 3, 5); 52 + test('5 - 3', 5 - 3, 2); 53 + test('4 * 3', 4 * 3, 12); 54 + test('12 / 4', 12 / 4, 3); 55 + test('10 % 3', 10 % 3, 1); 56 + test('2 ** 3', 2 ** 3, 8); 57 + 58 + test('true && true', true && true, true); 59 + test('true && false', true && false, false); 60 + test('true || false', true || false, true); 61 + test('false || false', false || false, false); 62 + test('!true', !true, false); 63 + test('!false', !false, true); 64 + 65 + test('5 & 3', 5 & 3, 1); 66 + test('5 | 3', 5 | 3, 7); 67 + test('5 ^ 3', 5 ^ 3, 6); 68 + test('~5', ~5, -6); 69 + test('5 << 1', 5 << 1, 10); 70 + test('5 >> 1', 5 >> 1, 2); 71 + test('-5 >>> 1', (-5 >>> 1) > 0, true); 72 + 73 + test('typeof 5', typeof 5, 'number'); 74 + test("typeof 'hello'", typeof 'hello', 'string'); 75 + test('typeof true', typeof true, 'boolean'); 76 + test('typeof undefined', typeof undefined, 'undefined'); 77 + test('typeof null', typeof null, 'object'); 78 + test('typeof {}', typeof {}, 'object'); 79 + test('typeof []', typeof [], 'object'); 80 + test('typeof function(){}', typeof function(){}, 'function'); 81 + 82 + test("'a' in {a:1}", 'a' in {a:1}, true); 83 + test("'b' in {a:1}", 'b' in {a:1}, false); 84 + 85 + test('[] instanceof Array', [] instanceof Array, true); 86 + test('{} instanceof Object', {} instanceof Object, true); 87 + 88 + test('ternary true', true ? 'yes' : 'no', 'yes'); 89 + test('ternary false', false ? 'yes' : 'no', 'no'); 90 + 91 + test('nullish ?? default', null ?? 'default', 'default'); 92 + test('nullish defined', 'value' ?? 'default', 'value'); 93 + test('nullish 0', 0 ?? 'default', 0); 94 + 95 + test('optional ?.', { a: { b: 1 } }?.a?.b, 1); 96 + test('optional ?. undefined', { a: {} }?.a?.b, undefined); 97 + test('optional ?. null chain', null?.a?.b, undefined); 98 + 99 + let x = 5; 100 + test('++x prefix', ++x, 6); 101 + test('x++ postfix', x++, 6); 102 + test('after x++', x, 7); 103 + test('--x prefix', --x, 6); 104 + 105 + let y = 10; 106 + y += 5; 107 + test('+= assignment', y, 15); 108 + y -= 3; 109 + test('-= assignment', y, 12); 110 + y *= 2; 111 + test('*= assignment', y, 24); 112 + y /= 4; 113 + test('/= assignment', y, 6); 114 + 115 + summary();
+36
examples/spec/path.js
··· 1 + import { test, summary } from './helpers.js'; 2 + import path from 'path'; 3 + 4 + console.log('Path Tests\n'); 5 + 6 + test('path.join', path.join('a', 'b', 'c'), 'a/b/c'); 7 + test('path.join with .', path.join('a', '.', 'b'), 'a/b'); 8 + test('path.join with ..', path.join('a', 'b', '..', 'c'), 'a/c'); 9 + 10 + test('path.resolve absolute', path.resolve('/a', 'b'), '/a/b'); 11 + test('path.resolve relative', typeof path.resolve('a', 'b'), 'string'); 12 + 13 + test('path.dirname', path.dirname('/a/b/c.txt'), '/a/b'); 14 + test('path.basename', path.basename('/a/b/c.txt'), 'c.txt'); 15 + test('path.basename with ext', path.basename('/a/b/c.txt', '.txt'), 'c'); 16 + test('path.extname', path.extname('/a/b/c.txt'), '.txt'); 17 + test('path.extname no ext', path.extname('/a/b/c'), ''); 18 + 19 + test('path.isAbsolute true', path.isAbsolute('/a/b'), true); 20 + test('path.isAbsolute false', path.isAbsolute('a/b'), false); 21 + 22 + test('path.normalize', path.normalize('/a/b/../c/./d'), '/a/c/d'); 23 + 24 + const parsed = path.parse('/home/user/file.txt'); 25 + test('path.parse root', parsed.root, '/'); 26 + test('path.parse dir', parsed.dir, '/home/user'); 27 + test('path.parse base', parsed.base, 'file.txt'); 28 + test('path.parse name', parsed.name, 'file'); 29 + test('path.parse ext', parsed.ext, '.txt'); 30 + 31 + test('path.format', path.format({ dir: '/home/user', base: 'file.txt' }), '/home/user/file.txt'); 32 + 33 + test('path.sep', path.sep, '/'); 34 + test('path.delimiter', path.delimiter, ':'); 35 + 36 + summary();
+60
examples/spec/promise.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Promise Tests\n'); 4 + 5 + let resolved = false; 6 + let resolvedValue = null; 7 + let p = new Promise((resolve) => resolve(42)); 8 + test('Promise instanceof', p instanceof Promise, true); 9 + 10 + p.then(v => { 11 + resolved = true; 12 + resolvedValue = v; 13 + }); 14 + 15 + let chainedValue = null; 16 + let p2 = new Promise(resolve => resolve(10)); 17 + p2.then(v => v * 2).then(v => { chainedValue = v; }); 18 + 19 + let caughtError = null; 20 + let p3 = new Promise((_, reject) => reject('error')); 21 + p3.catch(e => { caughtError = e; }); 22 + 23 + let staticValue = null; 24 + Promise.resolve('static').then(v => { staticValue = v; }); 25 + 26 + let tryValue = null; 27 + Promise.try(() => 'try').then(v => { tryValue = v; }); 28 + 29 + let finallyCalled = false; 30 + Promise.resolve('fin').finally(() => { finallyCalled = true; }); 31 + 32 + setTimeout(() => { 33 + test('resolve called', resolved, true); 34 + test('resolved value', resolvedValue, 42); 35 + test('chained value', chainedValue, 20); 36 + test('caught error', caughtError, 'error'); 37 + test('static resolve', staticValue, 'static'); 38 + test('Promise.try', tryValue, 'try'); 39 + test('finally called', finallyCalled, true); 40 + 41 + let allResolved = null; 42 + Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]) 43 + .then(arr => { allResolved = arr; }); 44 + 45 + let raceResolved = null; 46 + Promise.race([Promise.resolve('first'), Promise.resolve('second')]) 47 + .then(v => { raceResolved = v; }); 48 + 49 + let anyResolved = null; 50 + Promise.any([Promise.reject('fail'), Promise.resolve('success')]) 51 + .then(v => { anyResolved = v; }); 52 + 53 + setTimeout(() => { 54 + test('Promise.all length', allResolved?.length, 3); 55 + test('Promise.all values', allResolved?.[0] === 1 && allResolved?.[1] === 2, true); 56 + test('Promise.race first', raceResolved, 'first'); 57 + test('Promise.any success', anyResolved, 'success'); 58 + summary(); 59 + }, 10); 60 + }, 10);
+52
examples/spec/proxy.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Proxy Tests\n'); 4 + 5 + const target = { a: 1, b: 2 }; 6 + const handler = { 7 + get(obj, prop) { 8 + return prop in obj ? obj[prop] : 'default'; 9 + } 10 + }; 11 + const proxy = new Proxy(target, handler); 12 + 13 + test('proxy get existing', proxy.a, 1); 14 + test('proxy get missing', proxy.c, 'default'); 15 + 16 + const setHandler = { 17 + set(obj, prop, value) { 18 + obj[prop] = value * 2; 19 + return true; 20 + } 21 + }; 22 + const setProxy = new Proxy({}, setHandler); 23 + setProxy.x = 5; 24 + test('proxy set', setProxy.x, 10); 25 + 26 + const hasHandler = { 27 + has(obj, prop) { 28 + return prop.startsWith('_') ? false : prop in obj; 29 + } 30 + }; 31 + const hasProxy = new Proxy({ _private: 1, public: 2 }, hasHandler); 32 + test('proxy has public', 'public' in hasProxy, true); 33 + test('proxy has private', '_private' in hasProxy, false); 34 + 35 + const deleteHandler = { 36 + deleteProperty(obj, prop) { 37 + if (prop.startsWith('_')) return false; 38 + delete obj[prop]; 39 + return true; 40 + } 41 + }; 42 + const delProxy = new Proxy({ _keep: 1, remove: 2 }, deleteHandler); 43 + delete delProxy.remove; 44 + delete delProxy._keep; 45 + test('proxy delete allowed', delProxy.remove, undefined); 46 + test('proxy delete blocked', delProxy._keep, 1); 47 + 48 + const revocable = Proxy.revocable({ x: 1 }, {}); 49 + test('revocable proxy get', revocable.proxy.x, 1); 50 + revocable.revoke(); 51 + 52 + summary();
+51
examples/spec/reflect.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Reflect Tests\n'); 4 + 5 + const obj = { a: 1, b: 2 }; 6 + 7 + test('Reflect.get', Reflect.get(obj, 'a'), 1); 8 + 9 + Reflect.set(obj, 'c', 3); 10 + test('Reflect.set', obj.c, 3); 11 + 12 + test('Reflect.has true', Reflect.has(obj, 'a'), true); 13 + test('Reflect.has false', Reflect.has(obj, 'z'), false); 14 + 15 + Reflect.deleteProperty(obj, 'c'); 16 + test('Reflect.deleteProperty', obj.c, undefined); 17 + 18 + testDeep('Reflect.ownKeys', Reflect.ownKeys({ x: 1, y: 2 }), ['x', 'y']); 19 + 20 + function Point(x, y) { 21 + this.x = x; 22 + this.y = y; 23 + } 24 + const p = Reflect.construct(Point, [3, 4]); 25 + test('Reflect.construct x', p.x, 3); 26 + test('Reflect.construct y', p.y, 4); 27 + 28 + function greet(greeting) { 29 + return greeting + ' ' + this.name; 30 + } 31 + test('Reflect.apply', Reflect.apply(greet, { name: 'World' }, ['Hello']), 'Hello World'); 32 + 33 + const desc = Reflect.getOwnPropertyDescriptor(obj, 'a'); 34 + test('Reflect.getOwnPropertyDescriptor value', desc.value, 1); 35 + 36 + Reflect.defineProperty(obj, 'd', { value: 4, writable: true }); 37 + test('Reflect.defineProperty', obj.d, 4); 38 + 39 + test('Reflect.getPrototypeOf array', Reflect.getPrototypeOf([]) === Array.prototype, true); 40 + 41 + const newProto = { inherited: true }; 42 + const child = {}; 43 + Reflect.setPrototypeOf(child, newProto); 44 + test('Reflect.setPrototypeOf', child.inherited, true); 45 + 46 + test('Reflect.isExtensible', Reflect.isExtensible({}), true); 47 + 48 + const frozen = Object.freeze({}); 49 + test('Reflect.isExtensible frozen', Reflect.isExtensible(frozen), false); 50 + 51 + summary();
+52
examples/spec/regexp.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('RegExp Tests\n'); 4 + 5 + const re1 = new RegExp('hello'); 6 + test('RegExp source', re1.source, 'hello'); 7 + test('RegExp flags empty', re1.flags, ''); 8 + test('RegExp global false', re1.global, false); 9 + 10 + const re2 = new RegExp('test', 'g'); 11 + test('RegExp global flag', re2.global, true); 12 + test('RegExp flags g', re2.flags, 'g'); 13 + 14 + const re3 = new RegExp('pattern', 'gi'); 15 + test('RegExp multiple flags', re3.flags, 'gi'); 16 + test('RegExp global true', re3.global, true); 17 + test('RegExp ignoreCase true', re3.ignoreCase, true); 18 + 19 + const re4 = /hello/; 20 + test('literal source', re4.source, 'hello'); 21 + 22 + const re5 = /test/gi; 23 + test('literal flags', re5.flags, 'gi'); 24 + 25 + test('test true', /hello/.test('hello world'), true); 26 + test('test false', /hello/.test('goodbye world'), false); 27 + test('test case sensitive', /Hello/.test('hello'), false); 28 + test('test case insensitive', /Hello/i.test('hello'), true); 29 + 30 + testDeep('match simple', 'hello world'.match(/world/), ['world']); 31 + testDeep('match groups', 'hello'.match(/(h)(e)/), ['he', 'h', 'e']); 32 + 33 + test('exec not null', /o/.exec('hello') !== null, true); 34 + test('exec match', /o/.exec('hello')[0], 'o'); 35 + 36 + test('search found', 'hello world'.search(/world/), 6); 37 + test('search not found', 'hello world'.search(/xyz/), -1); 38 + 39 + test('replace', 'hello world'.replace(/world/, 'there'), 'hello there'); 40 + test('replace global', 'a-b-c'.replace(/-/g, '_'), 'a_b_c'); 41 + 42 + testDeep('split', 'a,b,c'.split(/,/), ['a', 'b', 'c']); 43 + 44 + const re6 = new RegExp('multi', 'm'); 45 + test('multiline flag', re6.multiline, true); 46 + 47 + const re7 = /foo/s; 48 + test('dotAll flag', re7.dotAll, true); 49 + 50 + test('sticky flag', /test/y.sticky, true); 51 + 52 + summary();
+55
examples/spec/run.js
··· 1 + import fs from 'fs'; 2 + import path from 'path'; 3 + import { spawn } from 'child_process'; 4 + 5 + const GREEN = '\x1b[32m'; 6 + const RED = '\x1b[31m'; 7 + const CYAN = '\x1b[36m'; 8 + const BOLD = '\x1b[1m'; 9 + const DIM = '\x1b[2m'; 10 + const RESET = '\x1b[0m'; 11 + 12 + const specDir = path.dirname(import.meta.url.replace('file://', '')); 13 + const files = fs 14 + .readdirSync(specDir) 15 + .filter(f => f.endsWith('.js') && f !== 'run.js' && f !== 'helpers.js') 16 + .sort(); 17 + 18 + let passed = 0; 19 + let failed = 0; 20 + 21 + console.log(`\n${BOLD}${CYAN}Running ${files.length} spec files...${RESET}\n`); 22 + 23 + for (const file of files) { 24 + const filePath = path.join(specDir, file); 25 + const name = path.basename(file, '.js'); 26 + 27 + try { 28 + const result = await new Promise((resolve, reject) => { 29 + const proc = spawn('ant', [filePath], { timeout: 30000 }); 30 + let stdout = ''; 31 + let stderr = ''; 32 + proc.stdout.on('data', d => (stdout += d)); 33 + proc.stderr.on('data', d => (stderr += d)); 34 + proc.on('close', code => resolve({ code, stdout, stderr })); 35 + proc.on('error', reject); 36 + }); 37 + 38 + if (result.code === 0) { 39 + console.log(`${GREEN}โœ“${RESET} ${name}`); 40 + passed++; 41 + } else { 42 + console.log(`${RED}โœ—${RESET} ${name}`); 43 + failed++; 44 + } 45 + } catch (e) { 46 + console.log(`${RED}โœ—${RESET} ${name} ${DIM}(error)${RESET}`); 47 + failed++; 48 + } 49 + } 50 + 51 + console.log(`\n${BOLD}Results:${RESET}`); 52 + console.log(` ${GREEN}${passed} passed${RESET}`); 53 + console.log(` ${RED}${failed} failed${RESET}\n`); 54 + 55 + process.exit(failed > 0 ? 1 : 0);
+44
examples/spec/set.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Set Tests\n'); 4 + 5 + const set = new Set(); 6 + 7 + set.add('value1'); 8 + set.add('value2'); 9 + set.add(42); 10 + set.add(true); 11 + 12 + test('set size after add', set.size(), 4); 13 + test('set has string', set.has('value1'), true); 14 + test('set has number', set.has(42), true); 15 + test('set has boolean', set.has(true), true); 16 + test('set has missing', set.has('missing'), false); 17 + 18 + test('set delete returns true', set.delete('value2'), true); 19 + test('set has after delete', set.has('value2'), false); 20 + test('set size after delete', set.size(), 3); 21 + 22 + set.add('value1'); 23 + test('set size after duplicate', set.size(), 3); 24 + 25 + set.add(123); 26 + set.add(null); 27 + 28 + test('set has 123', set.has(123), true); 29 + test('set has null', set.has(null), true); 30 + test('set size after more adds', set.size(), 5); 31 + 32 + set.clear(); 33 + test('set size after clear', set.size(), 0); 34 + test('set has after clear', set.has('value1'), false); 35 + 36 + set.add('a').add('b').add('c'); 37 + test('set chaining size', set.size(), 3); 38 + test('set chaining has a', set.has('a'), true); 39 + test('set chaining has b', set.has('b'), true); 40 + test('set chaining has c', set.has('c'), true); 41 + 42 + test('set delete nonexistent', set.delete('nonexistent'), false); 43 + 44 + summary();
+46
examples/spec/spread.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('Spread Tests\n'); 4 + 5 + const arr1 = [1, 2, 3]; 6 + const arr2 = [...arr1, 4, 5]; 7 + testDeep('spread array', arr2, [1, 2, 3, 4, 5]); 8 + 9 + const arr3 = [0, ...arr1]; 10 + testDeep('spread at start', arr3, [0, 1, 2, 3]); 11 + 12 + const arr4 = [0, ...arr1, 4]; 13 + testDeep('spread in middle', arr4, [0, 1, 2, 3, 4]); 14 + 15 + const copy = [...arr1]; 16 + testDeep('array copy', copy, [1, 2, 3]); 17 + test('array copy is new ref', copy !== arr1, true); 18 + 19 + const merged = [...[1, 2], ...[3, 4]]; 20 + testDeep('merge arrays', merged, [1, 2, 3, 4]); 21 + 22 + const obj1 = { a: 1, b: 2 }; 23 + const obj2 = { ...obj1, c: 3 }; 24 + test('spread object a', obj2.a, 1); 25 + test('spread object c', obj2.c, 3); 26 + 27 + const obj3 = { ...obj1, b: 10 }; 28 + test('spread override', obj3.b, 10); 29 + 30 + const objCopy = { ...obj1 }; 31 + test('object copy a', objCopy.a, 1); 32 + test('object copy is new ref', objCopy !== obj1, true); 33 + 34 + const mergedObj = { ...{ x: 1 }, ...{ y: 2 } }; 35 + test('merge objects x', mergedObj.x, 1); 36 + test('merge objects y', mergedObj.y, 2); 37 + 38 + function sum(a, b, c) { 39 + return a + b + c; 40 + } 41 + test('spread in call', sum(...[1, 2, 3]), 6); 42 + 43 + const chars = [...'hello']; 44 + testDeep('spread string', chars, ['h', 'e', 'l', 'l', 'o']); 45 + 46 + summary();
+86
examples/spec/strings.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('String Tests\n'); 4 + 5 + let str = 'hello world'; 6 + test('indexOf found', str.indexOf('world'), 6); 7 + test('indexOf first occurrence', str.indexOf('o'), 4); 8 + test('indexOf not found', str.indexOf('xyz'), -1); 9 + test('indexOf empty string', str.indexOf(''), 0); 10 + 11 + let js = 'JavaScript'; 12 + test('substring start end', js.substring(0, 4), 'Java'); 13 + test('substring start only', js.substring(4), 'Script'); 14 + test('substring swaps if end < start', js.substring(10, 4), 'Script'); 15 + 16 + let fox = 'The quick brown fox'; 17 + test('slice start end', fox.slice(0, 3), 'The'); 18 + test('slice start only', fox.slice(10), 'brown fox'); 19 + test('slice negative start', fox.slice(-3), 'fox'); 20 + test('slice negative end', fox.slice(0, -4), 'The quick brown'); 21 + 22 + let csv = 'apple,banana,cherry'; 23 + let parts = csv.split(','); 24 + test('split length', parts.length, 3); 25 + test('split first', parts[0], 'apple'); 26 + test('split last', parts[2], 'cherry'); 27 + 28 + let chars = 'hello'.split(''); 29 + test('split empty', chars.length, 5); 30 + test('split empty first', chars[0], 'h'); 31 + 32 + test('includes true', 'quick brown fox'.includes('quick'), true); 33 + test('includes false', 'quick brown fox'.includes('cat'), false); 34 + test('includes empty', 'hello'.includes(''), true); 35 + 36 + test('startsWith true', 'Hello, World!'.startsWith('Hello'), true); 37 + test('startsWith false', 'Hello, World!'.startsWith('World'), false); 38 + 39 + test('endsWith true', 'index.html'.endsWith('.html'), true); 40 + test('endsWith false', 'index.html'.endsWith('.js'), false); 41 + 42 + test('toUpperCase', 'hello'.toUpperCase(), 'HELLO'); 43 + test('toLowerCase', 'HELLO'.toLowerCase(), 'hello'); 44 + 45 + test('trim', ' hello '.trim(), 'hello'); 46 + test('trimStart', ' hello'.trimStart(), 'hello'); 47 + test('trimEnd', 'hello '.trimEnd(), 'hello'); 48 + 49 + test('padStart', '5'.padStart(3, '0'), '005'); 50 + test('padEnd', '5'.padEnd(3, '0'), '500'); 51 + 52 + test('repeat', 'ab'.repeat(3), 'ababab'); 53 + 54 + test('charAt', 'hello'.charAt(1), 'e'); 55 + test('charCodeAt', 'ABC'.charCodeAt(0), 65); 56 + 57 + test('replace', 'hello world'.replace('world', 'there'), 'hello there'); 58 + test('replaceAll', 'a-b-c'.replaceAll('-', '_'), 'a_b_c'); 59 + 60 + testDeep('match', 'test123'.match(/\d+/), ['123']); 61 + 62 + test('at positive', 'hello'.at(1), 'e'); 63 + test('at negative', 'hello'.at(-1), 'o'); 64 + 65 + test('length', 'hello'.length, 5); 66 + test('bracket access', 'hello'[0], 'h'); 67 + 68 + test('concat', 'hello'.concat(' ', 'world'), 'hello world'); 69 + 70 + test('lastIndexOf', 'hello world world'.lastIndexOf('world'), 12); 71 + 72 + test('String.fromCharCode', String.fromCharCode(65, 66, 67), 'ABC'); 73 + 74 + test('empty string length', ''.length, 0); 75 + test('empty indexOf', ''.indexOf('x'), -1); 76 + test('empty includes empty', ''.includes(''), true); 77 + test('empty startsWith empty', ''.startsWith(''), true); 78 + 79 + let template = `Value: ${1 + 2}`; 80 + test('template literal', template, 'Value: 3'); 81 + 82 + let multi = `line1 83 + line2`; 84 + test('multiline template', multi.includes('\n'), true); 85 + 86 + summary();
+72
examples/spec/switch.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Switch Tests\n'); 4 + 5 + let x = 2; 6 + let result = 0; 7 + switch (x) { 8 + case 1: result = 10; break; 9 + case 2: result = 20; break; 10 + case 3: result = 30; break; 11 + default: result = 99; 12 + } 13 + test('switch case 2', result, 20); 14 + 15 + let y = 1; 16 + let sum = 0; 17 + switch (y) { 18 + case 1: sum += 1; 19 + case 2: sum += 2; 20 + case 3: sum += 3; break; 21 + default: sum += 100; 22 + } 23 + test('switch fall-through', sum, 6); 24 + 25 + let fruit = 'apple'; 26 + let color = ''; 27 + switch (fruit) { 28 + case 'apple': color = 'red'; break; 29 + case 'banana': color = 'yellow'; break; 30 + case 'grape': color = 'purple'; break; 31 + default: color = 'unknown'; 32 + } 33 + test('switch string', color, 'red'); 34 + 35 + let z = 5; 36 + let msg = ''; 37 + switch (z) { 38 + case 1: msg = 'one'; break; 39 + case 2: msg = 'two'; break; 40 + default: msg = 'other'; 41 + } 42 + test('switch default', msg, 'other'); 43 + 44 + let a = 0; 45 + let aResult = ''; 46 + switch (a) { 47 + case 0: aResult = 'zero'; break; 48 + case 1: aResult = 'one'; break; 49 + } 50 + test('switch case 0', aResult, 'zero'); 51 + 52 + let b = true; 53 + let bResult = ''; 54 + switch (b) { 55 + case true: bResult = 'true'; break; 56 + case false: bResult = 'false'; break; 57 + } 58 + test('switch boolean', bResult, 'true'); 59 + 60 + function getGrade(score) { 61 + switch (true) { 62 + case score >= 90: return 'A'; 63 + case score >= 80: return 'B'; 64 + case score >= 70: return 'C'; 65 + default: return 'F'; 66 + } 67 + } 68 + test('switch expression A', getGrade(95), 'A'); 69 + test('switch expression B', getGrade(85), 'B'); 70 + test('switch expression F', getGrade(50), 'F'); 71 + 72 + summary();
+32
examples/spec/symbols.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Symbol Tests\n'); 4 + 5 + const sym1 = Symbol('test'); 6 + test('symbol typeof', typeof sym1, 'symbol'); 7 + 8 + const sym2 = Symbol('test'); 9 + test('symbols are unique', sym1 !== sym2, true); 10 + 11 + test('symbol description', sym1.description, 'test'); 12 + 13 + const sym3 = Symbol(); 14 + test('symbol without description', sym3.description, undefined); 15 + 16 + const obj = {}; 17 + const symKey = Symbol('key'); 18 + obj[symKey] = 'value'; 19 + test('symbol as key', obj[symKey], 'value'); 20 + 21 + const symFor1 = Symbol.for('shared'); 22 + const symFor2 = Symbol.for('shared'); 23 + test('Symbol.for same', symFor1 === symFor2, true); 24 + 25 + test('Symbol.keyFor', Symbol.keyFor(symFor1), 'shared'); 26 + test('Symbol.keyFor local', Symbol.keyFor(sym1), undefined); 27 + 28 + test('Symbol.iterator exists', typeof Symbol.iterator, 'symbol'); 29 + test('Symbol.toStringTag exists', typeof Symbol.toStringTag, 'symbol'); 30 + test('Symbol.hasInstance exists', typeof Symbol.hasInstance, 'symbol'); 31 + 32 + summary();
+34
examples/spec/textcodec.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + 3 + console.log('TextEncoder/TextDecoder Tests\n'); 4 + 5 + const encoder = new TextEncoder(); 6 + const decoder = new TextDecoder(); 7 + 8 + const encoded = encoder.encode('hello'); 9 + test('TextEncoder type', encoded instanceof Uint8Array, true); 10 + test('TextEncoder length', encoded.length, 5); 11 + test('TextEncoder byte 0', encoded[0], 104); 12 + test('TextEncoder byte 1', encoded[1], 101); 13 + 14 + const decoded = decoder.decode(encoded); 15 + test('TextDecoder', decoded, 'hello'); 16 + 17 + const utf8 = encoder.encode('ๆ—ฅๆœฌ่ชž'); 18 + test('UTF-8 encode length', utf8.length, 9); 19 + const utf8Decoded = decoder.decode(utf8); 20 + test('UTF-8 decode', utf8Decoded, 'ๆ—ฅๆœฌ่ชž'); 21 + 22 + const emoji = encoder.encode('๐Ÿ˜€'); 23 + test('emoji encode length', emoji.length, 4); 24 + test('emoji decode', decoder.decode(emoji), '๐Ÿ˜€'); 25 + 26 + const empty = encoder.encode(''); 27 + test('empty encode length', empty.length, 0); 28 + test('empty decode', decoder.decode(empty), ''); 29 + 30 + const roundtrip = 'Hello, ไธ–็•Œ! ๐ŸŽ‰'; 31 + const rt = decoder.decode(encoder.encode(roundtrip)); 32 + test('roundtrip', rt, roundtrip); 33 + 34 + summary();
+40
examples/spec/timers.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Timer Tests\n'); 4 + 5 + let results = {}; 6 + 7 + setTimeout(() => { 8 + results.timeout = true; 9 + }, 10); 10 + 11 + let count = 0; 12 + const interval = setInterval(() => { 13 + count++; 14 + if (count >= 3) { 15 + clearInterval(interval); 16 + results.interval = count; 17 + } 18 + }, 10); 19 + 20 + const canceled = setTimeout(() => { 21 + results.canceled = true; 22 + }, 10); 23 + clearTimeout(canceled); 24 + 25 + setImmediate(() => { 26 + results.immediate = true; 27 + }); 28 + 29 + queueMicrotask(() => { 30 + results.microtask = true; 31 + }); 32 + 33 + setTimeout(() => { 34 + test('setTimeout fired', results.timeout, true); 35 + test('setInterval count', results.interval, 3); 36 + test('clearTimeout worked', results.canceled, undefined); 37 + test('setImmediate fired', results.immediate, true); 38 + test('queueMicrotask fired', results.microtask, true); 39 + summary(); 40 + }, 100);
+35
examples/spec/typeof.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Typeof Tests\n'); 4 + 5 + test('typeof number', typeof 42, 'number'); 6 + test('typeof float', typeof 3.14, 'number'); 7 + test('typeof NaN', typeof NaN, 'number'); 8 + test('typeof Infinity', typeof Infinity, 'number'); 9 + 10 + test('typeof string', typeof 'hello', 'string'); 11 + test('typeof empty string', typeof '', 'string'); 12 + test('typeof template', typeof `template`, 'string'); 13 + 14 + test('typeof boolean true', typeof true, 'boolean'); 15 + test('typeof boolean false', typeof false, 'boolean'); 16 + 17 + test('typeof undefined', typeof undefined, 'undefined'); 18 + test('typeof undeclared', typeof undeclaredVar, 'undefined'); 19 + 20 + test('typeof null', typeof null, 'object'); 21 + 22 + test('typeof object', typeof {}, 'object'); 23 + test('typeof array', typeof [], 'object'); 24 + test('typeof date', typeof new Date(), 'object'); 25 + test('typeof regexp', typeof /test/, 'object'); 26 + 27 + test('typeof function', typeof function(){}, 'function'); 28 + test('typeof arrow', typeof (() => {}), 'function'); 29 + test('typeof class', typeof class {}, 'function'); 30 + 31 + test('typeof symbol', typeof Symbol('test'), 'symbol'); 32 + 33 + test('typeof bigint', typeof 123n, 'bigint'); 34 + 35 + summary();
+52
examples/spec/uri.js
··· 1 + import { test, testThrows, summary } from './helpers.js'; 2 + 3 + console.log('URI Encoding/Decoding Tests\n'); 4 + 5 + test('encodeURIComponent space', encodeURIComponent(' '), '%20'); 6 + test('encodeURIComponent special', encodeURIComponent('hello world!'), 'hello%20world!'); 7 + test('encodeURIComponent preserves unreserved', encodeURIComponent('abc123'), 'abc123'); 8 + test('encodeURIComponent preserves marks', encodeURIComponent("-_.!~*'()"), "-_.!~*'()"); 9 + test('encodeURIComponent reserved', encodeURIComponent(';/?:@&=+$,#'), '%3B%2F%3F%3A%40%26%3D%2B%24%2C%23'); 10 + test('encodeURIComponent Cyrillic', encodeURIComponent('ัˆะตะปะปั‹'), '%D1%88%D0%B5%D0%BB%D0%BB%D1%8B'); 11 + test('encodeURIComponent Chinese', encodeURIComponent('ไธญๆ–‡'), '%E4%B8%AD%E6%96%87'); 12 + test('encodeURIComponent emoji', encodeURIComponent('๐Ÿ˜€'), '%F0%9F%98%80'); 13 + test('encodeURIComponent empty', encodeURIComponent(''), ''); 14 + 15 + test('encodeURI preserves structure', encodeURI('https://example.com/path?q=hello world'), 'https://example.com/path?q=hello%20world'); 16 + test('encodeURI preserves reserved', encodeURI(';/?:@&=+$,#'), ';/?:@&=+$,#'); 17 + test('encodeURI space', encodeURI('hello world'), 'hello%20world'); 18 + test('encodeURI Cyrillic', encodeURI('https://mozilla.org/?x=ัˆะตะปะปั‹'), 'https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B'); 19 + test('encodeURI empty', encodeURI(''), ''); 20 + 21 + test('decodeURIComponent space', decodeURIComponent('%20'), ' '); 22 + test('decodeURIComponent special', decodeURIComponent('hello%20world%21'), 'hello world!'); 23 + test('decodeURIComponent Cyrillic', decodeURIComponent('%D1%88%D0%B5%D0%BB%D0%BB%D1%8B'), 'ัˆะตะปะปั‹'); 24 + test('decodeURIComponent Chinese', decodeURIComponent('%E4%B8%AD%E6%96%87'), 'ไธญๆ–‡'); 25 + test('decodeURIComponent emoji', decodeURIComponent('%F0%9F%98%80'), '๐Ÿ˜€'); 26 + test('decodeURIComponent reserved', decodeURIComponent('%3B%2F%3F%3A%40%26%3D%2B%24%2C%23'), ';/?:@&=+$,#'); 27 + test('decodeURIComponent plain', decodeURIComponent('hello'), 'hello'); 28 + test('decodeURIComponent empty', decodeURIComponent(''), ''); 29 + 30 + test('decodeURI Cyrillic', decodeURI('https://developer.mozilla.org/ru/docs/JavaScript_%D1%88%D0%B5%D0%BB%D0%BB%D1%8B'), 'https://developer.mozilla.org/ru/docs/JavaScript_ัˆะตะปะปั‹'); 31 + test('decodeURI preserves encoded reserved', decodeURI('https://example.com/docs/JavaScript%3A%20test'), 'https://example.com/docs/JavaScript%3A test'); 32 + test('decodeURI non-reserved', decodeURI('hello%20world'), 'hello world'); 33 + test('decodeURI empty', decodeURI(''), ''); 34 + 35 + const encoded = 'https://developer.mozilla.org/docs/JavaScript%3A%20a_scripting_language'; 36 + test('decodeURI preserves %3A', decodeURI(encoded), 'https://developer.mozilla.org/docs/JavaScript%3A a_scripting_language'); 37 + test('decodeURIComponent decodes %3A', decodeURIComponent(encoded), 'https://developer.mozilla.org/docs/JavaScript: a_scripting_language'); 38 + 39 + testThrows('decodeURIComponent invalid sequence', () => decodeURIComponent('%E0%A4%A')); 40 + testThrows('decodeURI invalid sequence', () => decodeURI('%E0%A4%A')); 41 + testThrows('decodeURIComponent incomplete %', () => decodeURIComponent('%')); 42 + testThrows('decodeURIComponent incomplete %X', () => decodeURIComponent('%2')); 43 + testThrows('decodeURIComponent invalid hex', () => decodeURIComponent('%GG')); 44 + 45 + const testStrings = ['hello world', 'foo=bar&baz=qux', 'ัˆะตะปะปั‹', 'ไธญๆ–‡ๆต‹่ฏ•', 'emoji: ๐Ÿ˜€๐ŸŽ‰', 'special: !@#$%^&*()', 'path/to/file.txt']; 46 + for (const str of testStrings) { 47 + const enc = encodeURIComponent(str); 48 + const dec = decodeURIComponent(enc); 49 + test(`roundtrip: "${str}"`, dec, str); 50 + } 51 + 52 + summary();
+47
examples/spec/url.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('URL Tests\n'); 4 + 5 + const url = new URL('https://user:pass@example.com:8080/path/to?query=value#hash'); 6 + 7 + test('URL href', url.href, 'https://user:pass@example.com:8080/path/to?query=value#hash'); 8 + test('URL protocol', url.protocol, 'https:'); 9 + test('URL username', url.username, 'user'); 10 + test('URL password', url.password, 'pass'); 11 + test('URL host', url.host, 'example.com:8080'); 12 + test('URL hostname', url.hostname, 'example.com'); 13 + test('URL port', url.port, '8080'); 14 + test('URL pathname', url.pathname, '/path/to'); 15 + test('URL search', url.search, '?query=value'); 16 + test('URL hash', url.hash, '#hash'); 17 + test('URL origin', url.origin, 'https://example.com:8080'); 18 + 19 + const url2 = new URL('/other', 'https://example.com'); 20 + test('URL with base', url2.href, 'https://example.com/other'); 21 + 22 + const url3 = new URL('https://example.com'); 23 + url3.pathname = '/new/path'; 24 + test('URL set pathname', url3.pathname, '/new/path'); 25 + 26 + const params = new URLSearchParams('a=1&b=2&a=3'); 27 + test('URLSearchParams get', params.get('a'), '1'); 28 + test('URLSearchParams getAll', params.getAll('a').length, 2); 29 + test('URLSearchParams has', params.has('b'), true); 30 + test('URLSearchParams has missing', params.has('c'), false); 31 + 32 + params.set('c', '4'); 33 + test('URLSearchParams set', params.get('c'), '4'); 34 + 35 + params.append('d', '5'); 36 + test('URLSearchParams append', params.get('d'), '5'); 37 + 38 + params.delete('b'); 39 + test('URLSearchParams delete', params.has('b'), false); 40 + 41 + test('URLSearchParams toString', params.toString().includes('a=1'), true); 42 + 43 + const url4 = new URL('https://example.com?x=1'); 44 + url4.searchParams.set('y', '2'); 45 + test('URL searchParams', url4.search, '?x=1&y=2'); 46 + 47 + summary();
+25
examples/spec/weakmap.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('WeakMap Tests\n'); 4 + 5 + const wm = new WeakMap(); 6 + const key1 = {}; 7 + const key2 = {}; 8 + 9 + wm.set(key1, 'value1'); 10 + wm.set(key2, 42); 11 + 12 + test('weakmap get', wm.get(key1), 'value1'); 13 + test('weakmap get number', wm.get(key2), 42); 14 + test('weakmap has true', wm.has(key1), true); 15 + test('weakmap has false', wm.has({}), false); 16 + 17 + wm.delete(key1); 18 + test('weakmap delete', wm.has(key1), false); 19 + 20 + const key3 = { id: 1 }; 21 + wm.set(key3, 'test'); 22 + wm.set(key3, 'updated'); 23 + test('weakmap overwrite', wm.get(key3), 'updated'); 24 + 25 + summary();
+25
examples/spec/weakset.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('WeakSet Tests\n'); 4 + 5 + const ws = new WeakSet(); 6 + const obj1 = {}; 7 + const obj2 = {}; 8 + 9 + ws.add(obj1); 10 + ws.add(obj2); 11 + 12 + test('weakset has true', ws.has(obj1), true); 13 + test('weakset has true 2', ws.has(obj2), true); 14 + test('weakset has false', ws.has({}), false); 15 + 16 + ws.delete(obj1); 17 + test('weakset delete', ws.has(obj1), false); 18 + test('weakset still has obj2', ws.has(obj2), true); 19 + 20 + const obj3 = { id: 1 }; 21 + ws.add(obj3); 22 + ws.add(obj3); 23 + test('weakset duplicate add', ws.has(obj3), true); 24 + 25 + summary();
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.0.15') 77 + version_conf.set('ANT_VERSION', '0.1.0.16') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80