function script1() { return arguments.length; } function script2(x) { return x; } function script3(x) { var o = arguments; return o[0]; } function genClosure() { var x = 3; eval("x = 4"); return function(y) { return x + y } }; var closed1 = genClosure(); var closed2 = genClosure(); var closed3 = genClosure(); var native1 = String.prototype.search; var native2 = String.prototype.match; var tricky1 = { call:function(x,y) { return y }, apply:function(x,y) { return y } }; test0(); test1(); test2(); test3(); function test0() { assertEq(script1.call(null), 0); assertEq(script1.call(null, 1), 1); assertEq(script1.call(null, 1,2), 2); assertEq(native1.call("aabc", /b/), 2); assertEq(native1.call("abc"), 0); assertEq(tricky1.call(null, 9), 9); assertEq(script1.apply(null), 0); assertEq(script1.apply(null, [1]), 1); assertEq(script1.apply(null, [1,2]), 2); assertEq(native1.apply("aabc", [/b/]), 2); assertEq(native1.apply("abc"), 0); assertEq(tricky1.apply(null, 1), 1); } test0(); function test1() { function f(arr) { for (var i = 0; i < 10; ++i) { for (var j = 0; j < arr.length; ++j) { arr[j].call('a'); arr[j].apply('a', []); var arg0 = []; arr[j].apply('a', arg0); (function() { arr[j].apply('a', arguments); })(); arr[j].call('a', 1); arr[j].apply('a', [1]); var arg0 = [1]; arr[j].apply('a', arg0); (function() { arr[j].apply('a', arguments); })(1); arr[j].call('a', 1,'g'); arr[j].apply('a', [1,'g']); var arg0 = [1,'g']; arr[j].apply('a', arg0); (function() { arr[j].apply('a', arguments); })(1,'g'); arr[j].call('a', 1,'g',3,4,5,6,7,8,9); arr[j].apply('a', [1,'g',3,4,5,6,7,8,9]); var arg0 = [1,'g',3,4,5,6,7,8,9]; arr[j].apply('a', arg0); (function() { arr[j].apply('a', arguments); })(1,'g',3,4,5,6,7,8,9); } } } f([script1, script1, script1, script1, script2, script2, script1, script2]); f([script1, script2, script3, script1, script2, script3, script3, script3]); f([script1, script2, script2, script2, script2, script3, script1, script2]); f([script1, script1, script1, native1, native1, native1, native1, script1]); f([native1, native1, native1, native2, native2, native2, native2, native1]); f([native1, native2, native1, native2, native1, native2, native1, native2]); f([native1, native1, native1, script1, script2, script2, native1, script3]); f([closed1, closed1, closed1, closed2, closed2, closed2, script3, script3]); f([closed1, closed2, closed1, closed2, closed1, closed2, closed1, closed2]); f([closed1, closed2, closed3, closed1, closed2, closed3, script1, script2]); f([closed1, closed1, closed1, closed2, closed2, closed2, native1, native2]); f([closed1, closed1, closed1, closed2, closed2, closed2, native1, native2]); f([native1, native1, native1, closed1, closed2, script1, script2, native2]); } // test things that break our speculation function test2() { var threw = false; try { (3).call(null, 1,2); } catch (e) { threw = true; } assertEq(threw, true); var threw = false; try { (3).apply(null, [1,2]); } catch (e) { threw = true; } assertEq(threw, true); var threw = false; try { var arr = [1,2]; (3).apply(null, arr); } catch (e) { threw = true; } assertEq(threw, true); function tryAndFail(o) { var threw = false; try { o.call(null, 1,2); } catch(e) { threw = true; } assertEq(threw, true); threw = false; try { o.apply(null, [1,2]); } catch(e) { threw = true; } assertEq(threw, true); } tryAndFail(1); tryAndFail({}); tryAndFail({call:{}, apply:{}}); tryAndFail({call:function() { throw "not js_fun_call"}, apply:function(){ throw "not js_fun_apply" }}); } // hit the stubs::CompileFunction path function test3() { function genFreshFunction(s) { return new Function(s, "return " + s); } function callIt(f) { assertEq(f.call(null, 1,2), 1); } callIt(script2); callIt(script2); callIt(script2); callIt(script2); callIt(genFreshFunction("x")); callIt(genFreshFunction("y")); callIt(genFreshFunction("z")); function applyIt(f) { var arr = [1,2]; assertEq(f.apply(null, arr), 1); } applyIt(script2); applyIt(script2); applyIt(script2); applyIt(script2); applyIt(genFreshFunction("x")); applyIt(genFreshFunction("y")); applyIt(genFreshFunction("z")); function applyIt1(f) { function g() { assertEq(f.apply(null, arguments), 1); } g(1,2); } applyIt1(script2); applyIt1(script2); applyIt1(script2); applyIt1(script2); applyIt1(genFreshFunction("x")); applyIt1(genFreshFunction("y")); applyIt1(genFreshFunction("z")); function applyIt2(f) { assertEq(f.apply(null, [1,2]), 1); } applyIt2(script2); applyIt2(script2); applyIt2(script2); applyIt2(script2); applyIt2(genFreshFunction("x")); applyIt2(genFreshFunction("y")); applyIt2(genFreshFunction("z")); }