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.

add more regression tests

+233
+147
tests/bench_includes_breakdown.cjs
··· 1 + function runBench(label, iterations, fn, options) { 2 + const warmup = options && options.warmup ? options.warmup : 5; 3 + const samples = options && options.samples ? options.samples : 10; 4 + 5 + for (let i = 0; i < warmup; i++) fn(); 6 + 7 + let min = Infinity; 8 + let max = -Infinity; 9 + let total = 0; 10 + let last = 0; 11 + 12 + for (let i = 0; i < samples; i++) { 13 + const start = performance.now(); 14 + last = fn(); 15 + const elapsed = performance.now() - start; 16 + if (elapsed < min) min = elapsed; 17 + if (elapsed > max) max = elapsed; 18 + total += elapsed; 19 + } 20 + 21 + const mean = total / samples; 22 + const opsPerMs = iterations / mean; 23 + 24 + console.log(label); 25 + console.log(` iterations: ${iterations}`); 26 + console.log(` result: ${last}`); 27 + console.log(` mean: ${mean.toFixed(3)} ms`); 28 + console.log(` min: ${min.toFixed(3)} ms`); 29 + console.log(` max: ${max.toFixed(3)} ms`); 30 + console.log(` ops/ms: ${opsPerMs.toFixed(1)}`); 31 + } 32 + 33 + const dense = []; 34 + for (let i = 0; i < 1024; i++) dense.push(i); 35 + 36 + const sparse = Array(1024); 37 + 38 + const genericOwn = { 39 + get length() { 40 + return 1024; 41 + }, 42 + get 1023() { 43 + return 1; 44 + } 45 + }; 46 + 47 + const genericProtoBase = { 1023: 1 }; 48 + const genericProto = Object.create(genericProtoBase); 49 + Object.defineProperty(genericProto, "length", { 50 + configurable: true, 51 + enumerable: true, 52 + get() { 53 + return 1024; 54 + } 55 + }); 56 + 57 + const proxy = new Proxy( 58 + { length: 4, 0: NaN, 1: 0, 2: NaN, 3: 1 }, 59 + { 60 + get(target, key) { 61 + return target[key]; 62 + } 63 + } 64 + ); 65 + 66 + const typed = new Uint32Array(1024); 67 + typed[1023] = 1; 68 + 69 + runBench("dense hit tail", 20000, () => { 70 + let hits = 0; 71 + for (let r = 0; r < 20000; r++) { 72 + if (dense.includes(1023)) hits++; 73 + } 74 + return hits; 75 + }); 76 + 77 + runBench("dense miss", 20000, () => { 78 + let hits = 0; 79 + for (let r = 0; r < 20000; r++) { 80 + if (dense.includes(-1)) hits++; 81 + } 82 + return hits; 83 + }); 84 + 85 + runBench("dense hit negative fromIndex", 20000, () => { 86 + let hits = 0; 87 + for (let r = 0; r < 20000; r++) { 88 + if (dense.includes(1023, -1)) hits++; 89 + } 90 + return hits; 91 + }); 92 + 93 + runBench("sparse includes(undefined)", 50000, () => { 94 + let hits = 0; 95 + for (let r = 0; r < 50000; r++) { 96 + if (sparse.includes(undefined)) hits++; 97 + } 98 + return hits; 99 + }); 100 + 101 + runBench("sparse miss non-undefined", 50000, () => { 102 + let hits = 0; 103 + for (let r = 0; r < 50000; r++) { 104 + if (sparse.includes(1)) hits++; 105 + } 106 + return hits; 107 + }); 108 + 109 + runBench("generic own getter", 20000, () => { 110 + let hits = 0; 111 + for (let r = 0; r < 20000; r++) { 112 + if ([].includes.call(genericOwn, 1, 1023)) hits++; 113 + } 114 + return hits; 115 + }); 116 + 117 + runBench("generic inherited value", 20000, () => { 118 + let hits = 0; 119 + for (let r = 0; r < 20000; r++) { 120 + if ([].includes.call(genericProto, 1, 1023)) hits++; 121 + } 122 + return hits; 123 + }); 124 + 125 + runBench("proxy NaN fromIndex", 20000, () => { 126 + let hits = 0; 127 + for (let r = 0; r < 20000; r++) { 128 + if (Array.prototype.includes.call(proxy, NaN, 1)) hits++; 129 + } 130 + return hits; 131 + }); 132 + 133 + runBench("typedarray hit", 50000, () => { 134 + let hits = 0; 135 + for (let r = 0; r < 50000; r++) { 136 + if (typed.includes(1)) hits++; 137 + } 138 + return hits; 139 + }); 140 + 141 + runBench("typedarray miss", 50000, () => { 142 + let hits = 0; 143 + for (let r = 0; r < 50000; r++) { 144 + if (typed.includes(2)) hits++; 145 + } 146 + return hits; 147 + });
+86
tests/test_array_includes_regression_big.cjs
··· 1 + const assert = require("node:assert"); 2 + 3 + function assertArrayIncludesRegressionSurface() { 4 + assert.strictEqual([1, 2, 3].includes(2), true); 5 + assert.strictEqual([1, 2, 3].includes(4), false); 6 + assert.strictEqual([1, 2, 3].includes(1, 1), false); 7 + assert.strictEqual([NaN].includes(NaN), true); 8 + assert.strictEqual([1, 2, 3].includes(3, -1), true); 9 + assert.strictEqual([1, 2, 3].includes(1, -1), false); 10 + 11 + assert.strictEqual([,].includes(undefined), true); 12 + assert.strictEqual(Array(4).includes(undefined), true); 13 + assert.strictEqual(Array(4).includes(1), false); 14 + 15 + const holey = []; 16 + holey[3] = "tail"; 17 + assert.strictEqual(holey.includes(undefined), true); 18 + assert.strictEqual(holey.includes("tail"), true); 19 + assert.strictEqual(holey.includes("tail", 4), false); 20 + 21 + let steps = 0; 22 + const generic = { 23 + get length() { 24 + steps += 1; 25 + return 6; 26 + }, 27 + get 2() { 28 + steps += 10; 29 + return "match"; 30 + }, 31 + get 4() { 32 + steps += 100; 33 + return "late"; 34 + } 35 + }; 36 + assert.strictEqual([].includes.call(generic, "match", 1), true); 37 + assert.strictEqual(steps, 11); 38 + 39 + const proto = { 3: "from-proto" }; 40 + const inherited = Object.create(proto); 41 + Object.defineProperty(inherited, "length", { 42 + configurable: true, 43 + enumerable: true, 44 + get() { 45 + return 5; 46 + } 47 + }); 48 + assert.strictEqual([].includes.call(inherited, "from-proto"), true); 49 + assert.strictEqual([].includes.call(inherited, undefined), true); 50 + 51 + const proxyLog = []; 52 + const proxy = new Proxy( 53 + { length: 4, 0: NaN, 1: "", 2: NaN, 3: "" }, 54 + { 55 + get(target, key) { 56 + proxyLog.push(String(key)); 57 + return target[key]; 58 + } 59 + } 60 + ); 61 + assert.strictEqual(Array.prototype.includes.call(proxy, NaN, 1), true); 62 + assert.deepStrictEqual(proxyLog, ["length", "1", "2"]); 63 + 64 + [ 65 + Int8Array, 66 + Uint8Array, 67 + Uint8ClampedArray, 68 + Int16Array, 69 + Uint16Array, 70 + Int32Array, 71 + Uint32Array, 72 + Float32Array, 73 + Float64Array 74 + ].forEach((TypedArray) => { 75 + const view = new TypedArray([1, 2, 3]); 76 + assert.strictEqual(view.includes(1), true); 77 + assert.strictEqual(view.includes(4), false); 78 + assert.strictEqual(view.includes(1, 1), false); 79 + }); 80 + 81 + const floatView = new Float64Array([1, NaN, 3]); 82 + assert.strictEqual(floatView.includes(NaN), true); 83 + } 84 + 85 + assertArrayIncludesRegressionSurface(); 86 + console.log("array includes regression surface passes");