OLD | NEW |
| (Empty) |
1 // Copyright 2013 the V8 project authors. All rights reserved. | |
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
3 // | |
4 // Redistribution and use in source and binary forms, with or without | |
5 // modification, are permitted provided that the following conditions | |
6 // are met: | |
7 // 1. Redistributions of source code must retain the above copyright | |
8 // notice, this list of conditions and the following disclaimer. | |
9 // 2. Redistributions in binary form must reproduce the above copyright | |
10 // notice, this list of conditions and the following disclaimer in the | |
11 // documentation and/or other materials provided with the distribution. | |
12 // | |
13 // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | |
14 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
15 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
16 // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y | |
17 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N | |
20 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
23 | |
24 description( | |
25 '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.' | |
26 ) | |
27 function child() | |
28 { | |
29 return (child.caller !== null); | |
30 } | |
31 | |
32 function parent() | |
33 { | |
34 return child(); | |
35 } | |
36 | |
37 var childHasCallerWhenExecutingGlobalCode = (child.caller !== null); | |
38 var childHasCallerWhenCalledWithoutParent = child(); | |
39 var childHasCallerWhenCalledFromWithinParent = parent(); | |
40 | |
41 shouldBe('childHasCallerWhenExecutingGlobalCode', 'false'); | |
42 shouldBe('childHasCallerWhenCalledWithoutParent', 'false'); | |
43 shouldBe('childHasCallerWhenCalledFromWithinParent', 'true') | |
44 | |
45 // 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). | |
46 function nonStrictCallee() { return nonStrictCallee.caller; } | |
47 function strictCallee() { "use strict"; return strictCallee.caller; } | |
48 function nonStrictCaller(x) { return x(); } | |
49 function strictCaller(x) { "use strict"; return x(); } | |
50 shouldBe("nonStrictCaller(nonStrictCallee)", "nonStrictCaller"); | |
51 shouldThrow("nonStrictCaller(strictCallee)", '"TypeError: Type error"'); | |
52 shouldThrow("strictCaller(nonStrictCallee)", '"TypeError: Function.caller used t
o retrieve strict caller"'); | |
53 shouldThrow("strictCaller(strictCallee)", '"TypeError: Type error"'); | |
54 | |
55 // .caller within a bound function reaches the caller, ignoring the binding. | |
56 var boundNonStrictCallee = nonStrictCallee.bind(); | |
57 var boundStrictCallee = strictCallee.bind(); | |
58 shouldBe("nonStrictCaller(boundNonStrictCallee)", "nonStrictCaller"); | |
59 shouldThrow("nonStrictCaller(boundStrictCallee)", '"TypeError: Type error"'); | |
60 shouldThrow("strictCaller(boundNonStrictCallee)", '"TypeError: Function.caller u
sed to retrieve strict caller"'); | |
61 shouldThrow("strictCaller(boundStrictCallee)", '"TypeError: Type error"'); | |
62 | |
63 // Check that .caller works (or throws) as expected, over an accessor call. | |
64 function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get;
} | |
65 function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set;
} | |
66 var nonStrictAccessor = { | |
67 get foo() { return getFooGetter(nonStrictAccessor).caller; }, | |
68 set foo(x) { if (getFooSetter(nonStrictAccessor).caller !==x) throw false; } | |
69 }; | |
70 var strictAccessor = { | |
71 get foo() { "use strict"; return getFooGetter(strictAccessor).caller; }, | |
72 set foo(x) { "use strict"; if (getFooSetter(strictAccessor).caller !==x) thr
ow false; } | |
73 }; | |
74 function nonStrictGetter(x) { return x.foo; } | |
75 function nonStrictSetter(x) { x.foo = nonStrictSetter; return true; } | |
76 function strictGetter(x) { "use strict"; return x.foo; } | |
77 function strictSetter(x) { "use strict"; x.foo = nonStrictSetter; return true; } | |
78 shouldBe("nonStrictGetter(nonStrictAccessor)", "nonStrictGetter"); | |
79 shouldBeTrue("nonStrictSetter(nonStrictAccessor)"); | |
80 shouldThrow("nonStrictGetter(strictAccessor)", '"TypeError: Type error"'); | |
81 shouldThrow("nonStrictSetter(strictAccessor)", '"TypeError: Type error"'); | |
82 shouldThrow("strictGetter(nonStrictAccessor)", '"TypeError: Function.caller used
to retrieve strict caller"'); | |
83 shouldThrow("strictSetter(nonStrictAccessor)", '"TypeError: Function.caller used
to retrieve strict caller"'); | |
84 shouldThrow("strictGetter(strictAccessor)", '"TypeError: Type error"'); | |
85 shouldThrow("strictSetter(strictAccessor)", '"TypeError: Type error"'); | |
OLD | NEW |