function assert(b, m = "") { if (!b) throw new Error("Bad assertion: " + m); } noInline(assert); const iterations = 20000; function test1() { function bar(a, b, ...args) { return args.length; } noInline(bar); for (let i = 0; i < iterations; i++) { assert(bar() === 0, bar()); assert(bar(i) === 0); assert(bar(i, i) === 0); assert(bar(i, i, i) === 1); assert(bar(i, i, i, i, i) === 3); } } function shallowEq(a, b) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (a.length !== b.length) return false; } return true; } noInline(shallowEq); function test2() { function jaz(a, b, ...args) { let result = []; for (let i = 0; i < args.length; i++) { result.push(args[i]); } return result; } noInline(jaz); function jaz2(...args) { function kaz(a, b, ...args) { let result = []; for (let i = 0; i < args.length; i++) { result.push(args[i]); } return result; } return kaz.apply(null, args); } noInline(jaz2); for (let f of [jaz, jaz2]) { for (let i = 0; i < iterations; i++) { let r = f(); assert(!r.length); r = f(i); assert(!r.length); r = f(i, i) assert(!r.length); r = f(i, i, i) assert(r.length === 1); assert(shallowEq(r, [i])); r = f(i, i, i) assert(r.length === 1); assert(shallowEq(r, [i])); r = f(i, i, i, i*2, i*4) assert(r.length === 3); assert(shallowEq(r, [i, i*2, i*4])); } } } function test3() { function foo(...args) { return args; } function baz(a, b, c, ...args) { return foo.apply(null, args); } function jaz(a, b, c, d, e, f) { return baz(a, b, c, d, e, f); } noInline(jaz); for (let i = 0; i < iterations; i++) { let r = jaz(); assert(r.length === 3); assert(shallowEq(r, [undefined, undefined, undefined])); r = jaz(i, i); assert(r.length === 3); assert(shallowEq(r, [undefined, undefined, undefined])); r = jaz(i, i, i); assert(r.length === 3); assert(shallowEq(r, [undefined, undefined, undefined])); r = jaz(i, i, i, i); assert(r.length === 3); assert(shallowEq(r, [i, undefined, undefined])); r = jaz(i, i, i, i, i, i); assert(r.length === 3); assert(shallowEq(r, [i, i, i])); } } function test4() { function baz(...args) { return args; } function jaz(a, b, ...args) { return baz.apply(null, args); } noInline(jaz); for (let i = 0; i < iterations; i++) { let r = jaz(); assert(r.length === 0); r = jaz(i); assert(r.length === 0); r = jaz(i, i); assert(r.length === 0); r = jaz(i, i, i); assert(r.length === 1); assert(shallowEq(r, [i])); r = jaz(i, i, i, i*10); assert(r.length === 2); assert(shallowEq(r, [i, i*10])); let o = {}; r = jaz(i, i, i, i*10, o); assert(r.length === 3); assert(shallowEq(r, [i, i*10, o])); } } function test5() { function baz(...args) { return args; } noInline(baz); function jaz(a, b, ...args) { return baz.apply(null, args); } noInline(jaz); for (let i = 0; i < iterations; i++) { let r = jaz(); assert(r.length === 0); r = jaz(i); assert(r.length === 0); r = jaz(i, i); assert(r.length === 0); r = jaz(i, i, i); assert(r.length === 1); assert(shallowEq(r, [i])); r = jaz(i, i, i, i*10); assert(r.length === 2); assert(shallowEq(r, [i, i*10])); let o = {}; r = jaz(i, i, i, i*10, o); assert(r.length === 3); assert(shallowEq(r, [i, i*10, o])); } } function test6() { "use strict"; function baz(...args) { return args; } noInline(baz); function jaz(a, b, ...args) { return baz.apply(null, args); } noInline(jaz); for (let i = 0; i < iterations; i++) { let r = jaz(); assert(r.length === 0); r = jaz(i); assert(r.length === 0); r = jaz(i, i); assert(r.length === 0); r = jaz(i, i, i); assert(r.length === 1); assert(shallowEq(r, [i])); r = jaz(i, i, i, i*10); assert(r.length === 2); assert(shallowEq(r, [i, i*10])); let o = {}; r = jaz(i, i, i, i*10, o); assert(r.length === 3); assert(shallowEq(r, [i, i*10, o])); } } function test7() { let shouldExit = false; function baz(...args) { if (shouldExit) { OSRExit(); return [args.length, args[0], args[1], args[2]]; } return [args.length, args[0], args[1], args[2]]; } function jaz(a, b, ...args) { return baz.apply(null, args); } noInline(jaz); function check(i) { let [length, a, b, c] = jaz(); assert(length === 0); assert(a === undefined); assert(b === undefined); assert(c === undefined); [length, a, b, c] = jaz(i); assert(length === 0); assert(a === undefined); assert(b === undefined); assert(c === undefined); [length, a, b, c] = jaz(i, i); assert(length === 0); assert(a === undefined); assert(b === undefined); assert(c === undefined); [length, a, b, c] = jaz(i, i, i); assert(length === 1); assert(a === i, JSON.stringify(a)); assert(b === undefined); assert(c === undefined); [length, a, b, c] = jaz(i, i, i, i*10); assert(length === 2); assert(a === i); assert(b === i*10); assert(c === undefined); let o = {oooo:20}; [length, a, b, c] = jaz(i, i, i, i*10, o); assert(length === 3); assert(a === i); assert(b === i*10); assert(c === o); } shouldExit = true; for (let i = 0; i < 400; i++) { check(i); } shouldExit = false; for (let i = 0; i < iterations; i++) { check(i); } shouldExit = false; check(10); } function test8() { let shouldExit = false; function baz(...args) { if (shouldExit) { OSRExit(); return args; } return args; } function jaz(a, b, ...args) { return baz.apply(null, args); } noInline(jaz); function check(i) { let args = jaz(); assert(args.length === 0); args = jaz(i); assert(args.length === 0); args = jaz(i, i); assert(args.length === 0); args = jaz(i, i, i); assert(args.length === 1); assert(args[0] === i); args = jaz(i, i, i, i*10); assert(args.length === 2); assert(args[0] === i); assert(args[1] === i*10); let o = {oooo:20}; args = jaz(i, i, i, i*10, o); assert(args.length === 3); assert(args[0] === i); assert(args[1] === i*10); assert(args[2] === o); } shouldExit = true; for (let i = 0; i < 400; i++) { check(i); } shouldExit = false; for (let i = 0; i < iterations; i++) { check(i); } shouldExit = false; check(10); } function test9() { let shouldExit = false; function baz(a, ...args) { if (shouldExit) { OSRExit(); return [args.length, args[0], args[1]]; } return [args.length, args[0], args[1]]; } function jaz(...args) { return baz.apply(null, args); } noInline(jaz); function check(i) { let [length, a, b] = jaz(); assert(length === 0); [length, a, b] = jaz(i); assert(length === 0); assert(a === undefined); assert(b === undefined); [length, a, b] = jaz(i, i + 1); assert(length === 1); assert(a === i+1); assert(b === undefined); [length, a, b] = jaz(i, i+1, i+2); assert(length === 2); assert(a === i+1); assert(b === i+2); let o = {oooo:20}; [length, a, b] = jaz(i, i+1, o); assert(length === 2); assert(a === i+1); assert(b === o); } shouldExit = true; for (let i = 0; i < 400; i++) { check(i); } shouldExit = false; for (let i = 0; i < iterations; i++) { check(i); } shouldExit = false; check(10); } function test10() { function baz(a, b, c, ...args) { return [args.length, args[0], args[1], args[2], args[3]]; } function jaz(a, b, c, d, e, f) { return baz(a, b, c, d, e, f); } noInline(jaz); for (let i = 0; i < iterations; i++) { let [length, a, b, c, d] = jaz(1, 2, 3, 4, 5, 6); assert(length === 3); assert(a === 4); assert(b === 5); assert(c === 6); assert(d === undefined); } } function test11() { function bar(...args) { return args; } noInline(bar); function foo(a, b, c, d, ...args) { return bar.apply(null, args); } noInline(foo); function makeArguments(args) { return [1,2,3,4, ...args]; } for (let i = 0; i < iterations; i++) { function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); } let a = [{}, 25, 50]; test(); a = []; test(); a = [{foo: 20}]; test(); a = [10, 20, 30, 40, 50, 60, 70, 80]; test(); } } function test12() { "use strict"; let thisValue = {}; function getThisValue() { return thisValue; } noInline(getThisValue); function bar(...args) { assert(this === thisValue); return args; } noInline(bar); function foo(a, b, c, d, ...args) { return bar.apply(getThisValue(), args); } noInline(foo); function makeArguments(args) { return [1,2,3,4, ...args]; } for (let i = 0; i < iterations; i++) { function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); } let a = [{}, 25, 50]; test(); a = []; test(); a = [{foo: 20}]; test(); a = [10, 20, 30, 40, 50, 60, 70, 80]; test(); } } function test13() { "use strict"; function bar(...args) { return args; } noInline(bar); function top(a, b, c, d, ...args) { return bar.apply(null, args); } function foo(...args) { let r = top.apply(null, args); return r; } noInline(foo); function makeArguments(args) { return [1,2,3,4, ...args]; } for (let i = 0; i < iterations; i++) { function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); } let a = [{}, 25, 50]; test(); a = []; test(); a = [10, 20, 30, 40, 50, 60, 70, 80]; test(); } } function test14() { "use strict"; function bar(...args) { return args; } noInline(bar); function top(a, b, c, d, ...args) { return bar.apply(null, args); } function foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) { return top(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } noInline(foo); function makeArguments(args) { let r = [1,2,3,4, ...args]; while (r.length < foo.length) r.push(undefined); return r; } for (let i = 0; i < iterations; i++) { function test() { let args = makeArguments(a); assert(shallowEq(args.slice(4), foo.apply(null, args))); } let a = [{}, 25, 50]; test(); a = []; test(); a = [10, 20, 30, 40, 50, 60, 70, 80]; test(); } } function test15() { "use strict"; function bar(...args) { return args; } noInline(bar); function top(a, b, c, d, ...args) { return bar.apply(null, args); } function foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) { let r = top(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); return r; } noInline(foo); function makeArguments(args) { let r = [1,2,3,4, ...args]; while (r.length < foo.length) r.push(undefined); return r; } for (let i = 0; i < iterations; i++) { function test() { let args = makeArguments(a); assert(shallowEq(args.slice(4), foo.apply(null, args))); } let a = [{}, 25, 50]; test(); a = []; test(); a = [10, 20, 30, 40, 50, 60, 70, 80]; test(); } } let start = Date.now(); test1(); test2(); test3(); test4(); test5(); test6(); test7(); test8(); test9(); test10(); test11(); test12(); test13(); test14(); test15(); const verbose = false; if (verbose) print(Date.now() - start);