| /////////////////////////////// |
| // empty bodies |
| |
| function empty1() { ; } |
| shouldBe("empty1()", "undefined"); |
| |
| function empty2() { } |
| shouldBe("empty2()", "undefined"); |
| |
| var g = 2; |
| var obj = new Object(); |
| with (obj) { |
| obj.func = function(a) { return g*l*a; }; |
| } |
| obj.l = 3; |
| |
| shouldBe("obj.func(11)", "66"); |
| |
| /////////////////////////////// |
| |
| function ctor(xx) { |
| this.x = xx; |
| this.dummy = new Array(); // once broke the returned completion |
| } |
| |
| c = new ctor(11); |
| shouldBe("c.x", "11"); |
| |
| /////////////////////////////// |
| // anonymous functions |
| /////////////////////////////// |
| |
| f = function (arg) { |
| return arg; |
| }; |
| |
| |
| shouldBe("f('bbbbb')", "'bbbbb'"); |
| |
| |
| function f() {return 1;}; |
| |
| // just verify that this can be parsed |
| Math.round(function anon() { }); |
| |
| /////////////////////////////// |
| // arguments object |
| /////////////////////////////// |
| |
| function foo() { |
| var result = "|"; |
| for (i = 0; i < arguments.length; i++) |
| result += arguments[i] + "|"; |
| return result; |
| } |
| |
| shouldBe("foo()", "'|'"); |
| shouldBe("foo('bar')", "'|bar|'"); |
| shouldBe("foo('bar', 'x')", "'|bar|x|'"); |
| |
| function foo2(a) { |
| var i = 0; |
| for(a in arguments) // should be enumerable |
| i++; |
| return i; |
| } |
| |
| shouldBe("foo2(7)", "1"); |
| |
| // I have my doubts about the standard conformance of this |
| function foo3(i, j) { |
| switch(i) { |
| case 0: |
| return foo3.arguments.length; |
| case 1: |
| return foo3.arguments; |
| case 2: |
| return foo3.j; |
| } |
| } |
| |
| shouldBe("foo3(0, 99)", "2"); |
| shouldBe("foo3(1, 99).length", "2"); |
| //shouldBe("foo3(2, 99)", "99"); // IE doesn't support this either |
| |
| /////////////////////////////// |
| // nested function declarations |
| /////////////////////////////// |
| |
| function nest0(a, b) |
| { |
| function nest1(c) { return c*c; } |
| return nest1(a*b); |
| } |
| shouldBe("nest0(2,3)", "36"); |
| |
| /////////////////////////////// |
| // Function object |
| /////////////////////////////// |
| |
| shouldBe("(new Function('return 11;'))()", "11"); |
| shouldBe("(new Function('', 'return 22;'))()", "22"); |
| shouldBe("(new Function('a', 'b', 'return a*b;'))(11, 3)", "33"); |
| shouldBe("(new Function(' a ', ' b ', 'return a*b;'))(11, 4)", "44"); |
| shouldBe("(new Function(' a,b ', ' c ', 'return a*b;'))(11, 5)", "55"); |
| shouldBe("(new Function(' a,b ', ' c3 ', 'return a*b;'))(11, 6)", "66"); |
| |
| |
| /////////////////////////////// |
| // length property |
| function funcp3(a, b, c) { } |
| shouldBe("funcp3.length", "3"); |
| shouldBe("(function(a, b, c, d) { }).length", "4"); |
| shouldBe("(new Function('a', 'b', '')).length", "2"); |
| |
| // recursive call |
| function f4(i) |
| { |
| return i == 1 ? 1 : i*f4(i-1); |
| } |
| |
| shouldBe("f4(4)", "24"); |
| |
| function f5(a) { |
| return f6(); |
| } |
| |
| function f6() { |
| return f5.arguments[0]; |
| } |
| |
| shouldBe("f5(11)", "11"); |
| shouldBe("f5.arguments", "null"); |
| |
| /////////////////////////////// |
| // calling conventions |
| /////////////////////////////// |
| |
| function manipulate(x) { |
| x[0] = 99; // should operate on reference |
| x = "nothing"; // should detach |
| } |
| var arr = new Array(1, 2, 3); |
| manipulate(arr); |
| shouldBe("arr[0]", "99"); |
| arr = [1, 2, 3]; |
| manipulate(arr); |
| shouldBe("arr[0]", "99"); |
| |
| /////////////////////////////// |
| // toString() on functions |
| /////////////////////////////// |
| |
| function orgFunc(s) { return 'Hello ' + s; } |
| eval("var orgFuncClone = " + orgFunc); |
| shouldBe("typeof orgFuncClone", "'function'"); |
| shouldBe("orgFuncClone('world')", "'Hello world'"); |
| |
| function groupFunc(a, b) { return (a+b)*3; } // check for () being preserved |
| eval("var groupClone = " + groupFunc); |
| shouldBe("groupClone(1, 2)", "9"); |
| |
| var sinStr = 'function sin() {\n [native code]\n}' |
| shouldBe("String(Math.sin)", "sinStr"); |
| |
| /////////////////////////////// |
| // shadowed functions |
| /////////////////////////////// |
| |
| function shadow() { return 1; } |
| function shadow() { return 2; } |
| shouldBe("shadow()", "2"); |
| |
| /////////////////////////////// |
| // nested functions |
| |
| var nest_property = "global nest"; |
| |
| function nested_outer() { |
| |
| var nest_property = "inner nest"; |
| |
| function nested_inner() { |
| return nest_property; |
| } |
| |
| return nested_inner; |
| } |
| |
| function not_nested() { |
| return nest_property; |
| } |
| |
| nested_outer.nest_property = "outer nest"; |
| |
| var nested = nested_outer(); |
| var nestedret = nested(); |
| shouldBe("nestedret","'inner nest'"); |
| |
| var not_nestedret = not_nested(); |
| shouldBe("not_nestedret","'global nest'"); |
| |
| /////////////////////////////// |
| // other properties |
| /////////////////////////////// |
| function sample() { } |
| shouldBeUndefined("sample.prototype.prototype"); |
| shouldBeTrue("sample.prototype.constructor == sample"); |
| |
| var caught = false; |
| try { |
| sample.apply(1, 1); // invalid argument |
| } catch(dummy) { |
| caught = true; |
| } |
| shouldBeTrue("caught"); |
| |
| |
| function functionWithVarOverride(a) { |
| var a = 2; |
| return a; |
| } |
| |
| shouldBe("functionWithVarOverride(1)", "2"); |