| OLD | NEW |
| (Empty) |
| 1 description( | |
| 2 'This tests for caller property in functions. Only functions that are called fro
m inside of other functions and have a parent should have this property set. Tes
ts return true when caller is found and false when the caller is null.' | |
| 3 ) | |
| 4 function child() | |
| 5 { | |
| 6 return (child.caller !== null); | |
| 7 } | |
| 8 | |
| 9 function parent() | |
| 10 { | |
| 11 return child(); | |
| 12 } | |
| 13 | |
| 14 var childHasCallerWhenExecutingGlobalCode = (child.caller !== null); | |
| 15 var childHasCallerWhenCalledWithoutParent = child(); | |
| 16 var childHasCallerWhenCalledFromWithinParent = parent(); | |
| 17 | |
| 18 shouldBe('childHasCallerWhenExecutingGlobalCode', 'false'); | |
| 19 shouldBe('childHasCallerWhenCalledWithoutParent', 'false'); | |
| 20 shouldBe('childHasCallerWhenCalledFromWithinParent', 'true') | |
| 21 | |
| 22 // The caller property should throw in strict mode, and a non-strict function ca
nnot use caller to reach a strict caller (see ES5.1 15.3.5.4). | |
| 23 function nonStrictCallee() { return nonStrictCallee.caller; } | |
| 24 function strictCallee() { "use strict"; return strictCallee.caller; } | |
| 25 function nonStrictCaller(x) { return x(); } | |
| 26 function strictCaller(x) { "use strict"; return x(); } | |
| 27 shouldBe("nonStrictCaller(nonStrictCallee)", "nonStrictCaller"); | |
| 28 shouldThrow("nonStrictCaller(strictCallee)", '"TypeError: Type error"'); | |
| 29 shouldThrow("strictCaller(nonStrictCallee)", '"TypeError: Function.caller used t
o retrieve strict caller"'); | |
| 30 shouldThrow("strictCaller(strictCallee)", '"TypeError: Type error"'); | |
| 31 | |
| 32 // .caller within a bound function reaches the caller, ignoring the binding. | |
| 33 var boundNonStrictCallee = nonStrictCallee.bind(); | |
| 34 var boundStrictCallee = strictCallee.bind(); | |
| 35 shouldBe("nonStrictCaller(boundNonStrictCallee)", "nonStrictCaller"); | |
| 36 shouldThrow("nonStrictCaller(boundStrictCallee)", '"TypeError: Type error"'); | |
| 37 shouldThrow("strictCaller(boundNonStrictCallee)", '"TypeError: Function.caller u
sed to retrieve strict caller"'); | |
| 38 shouldThrow("strictCaller(boundStrictCallee)", '"TypeError: Type error"'); | |
| 39 | |
| 40 // Check that .caller works (or throws) as expected, over an accessor call. | |
| 41 function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get;
} | |
| 42 function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set;
} | |
| 43 var nonStrictAccessor = { | |
| 44 get foo() { return getFooGetter(nonStrictAccessor).caller; }, | |
| 45 set foo(x) { if (getFooSetter(nonStrictAccessor).caller !==x) throw false; } | |
| 46 }; | |
| 47 var strictAccessor = { | |
| 48 get foo() { "use strict"; return getFooGetter(strictAccessor).caller; }, | |
| 49 set foo(x) { "use strict"; if (getFooSetter(strictAccessor).caller !==x) thr
ow false; } | |
| 50 }; | |
| 51 function nonStrictGetter(x) { return x.foo; } | |
| 52 function nonStrictSetter(x) { x.foo = nonStrictSetter; return true; } | |
| 53 function strictGetter(x) { "use strict"; return x.foo; } | |
| 54 function strictSetter(x) { "use strict"; x.foo = nonStrictSetter; return true; } | |
| 55 shouldBe("nonStrictGetter(nonStrictAccessor)", "nonStrictGetter"); | |
| 56 shouldBeTrue("nonStrictSetter(nonStrictAccessor)"); | |
| 57 shouldThrow("nonStrictGetter(strictAccessor)", '"TypeError: Type error"'); | |
| 58 shouldThrow("nonStrictSetter(strictAccessor)", '"TypeError: Type error"'); | |
| 59 shouldThrow("strictGetter(nonStrictAccessor)", '"TypeError: Function.caller used
to retrieve strict caller"'); | |
| 60 shouldThrow("strictSetter(nonStrictAccessor)", '"TypeError: Function.caller used
to retrieve strict caller"'); | |
| 61 shouldThrow("strictGetter(strictAccessor)", '"TypeError: Type error"'); | |
| 62 shouldThrow("strictSetter(strictAccessor)", '"TypeError: Type error"'); | |
| OLD | NEW |