- Revision
- 109461
- Author
- [email protected]
- Date
- 2012-03-01 16:12:58 -0800 (Thu, 01 Mar 2012)
Log Message
ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
https://bugs.webkit.org/show_bug.cgi?id=80011
Reviewed by Oliver Hunt.
Also, fix getting the caller from within a bound function, for within a getter,
or setter (make our implementation match other browsers).
Source/_javascript_Core:
* interpreter/Interpreter.cpp:
(JSC::getCallerInfo):
- Allow this to get the caller of host functions.
(JSC::Interpreter::retrieveCallerFromVMCode):
- This should use getCallerInfo, and should skip over function bindings.
* runtime/JSFunction.cpp:
(JSC::JSFunction::callerGetter):
- This should never return a strict-mode function.
LayoutTests:
* fast/js/caller-property-expected.txt:
* fast/js/script-tests/caller-property.js:
- Add test cases covering permutations of caller/callee being strict/non-strict,
And for callee being a getter/setter/bound.
* fast/js/stack-trace-expected.txt:
- Allow stack tracing over host functions.
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (109460 => 109461)
--- trunk/LayoutTests/ChangeLog 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/ChangeLog 2012-03-02 00:12:58 UTC (rev 109461)
@@ -1,3 +1,20 @@
+2012-03-01 Gavin Barraclough <[email protected]>
+
+ ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
+ https://bugs.webkit.org/show_bug.cgi?id=80011
+
+ Reviewed by Oliver Hunt.
+
+ Also, fix getting the caller from within a bound function, for within a getter,
+ or setter (make our implementation match other browsers).
+
+ * fast/js/caller-property-expected.txt:
+ * fast/js/script-tests/caller-property.js:
+ - Add test cases covering permutations of caller/callee being strict/non-strict,
+ And for callee being a getter/setter/bound.
+ * fast/js/stack-trace-expected.txt:
+ - Allow stack tracing over host functions.
+
2012-03-01 Xingnan Wang <[email protected]>
Enable IPP for Biquad filter
Modified: trunk/LayoutTests/fast/js/caller-property-expected.txt (109460 => 109461)
--- trunk/LayoutTests/fast/js/caller-property-expected.txt 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/caller-property-expected.txt 2012-03-02 00:12:58 UTC (rev 109461)
@@ -6,6 +6,22 @@
PASS childHasCallerWhenExecutingGlobalCode is false
PASS childHasCallerWhenCalledWithoutParent is false
PASS childHasCallerWhenCalledFromWithinParent is true
+PASS nonStrictCaller(nonStrictCallee) is nonStrictCaller
+PASS nonStrictCaller(strictCallee) threw exception TypeError: Type error.
+PASS strictCaller(nonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictCaller(strictCallee) threw exception TypeError: Type error.
+PASS nonStrictCaller(boundNonStrictCallee) is nonStrictCaller
+PASS nonStrictCaller(boundStrictCallee) threw exception TypeError: Type error.
+PASS strictCaller(boundNonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictCaller(boundStrictCallee) threw exception TypeError: Type error.
+PASS nonStrictGetter(nonStrictAccessor) is nonStrictGetter
+PASS nonStrictSetter(nonStrictAccessor) is true
+PASS nonStrictGetter(strictAccessor) threw exception TypeError: Type error.
+PASS nonStrictSetter(strictAccessor) threw exception TypeError: Type error.
+PASS strictGetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictSetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictGetter(strictAccessor) threw exception TypeError: Type error.
+PASS strictSetter(strictAccessor) threw exception TypeError: Type error.
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/js/script-tests/caller-property.js (109460 => 109461)
--- trunk/LayoutTests/fast/js/script-tests/caller-property.js 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/script-tests/caller-property.js 2012-03-02 00:12:58 UTC (rev 109461)
@@ -18,3 +18,45 @@
shouldBe('childHasCallerWhenExecutingGlobalCode', 'false');
shouldBe('childHasCallerWhenCalledWithoutParent', 'false');
shouldBe('childHasCallerWhenCalledFromWithinParent', 'true')
+
+// The caller property should throw in strict mode, and a non-strict function cannot use caller to reach a strict caller (see ES5.1 15.3.5.4).
+function nonStrictCallee() { return nonStrictCallee.caller; }
+function strictCallee() { "use strict"; return strictCallee.caller; }
+function nonStrictCaller(x) { return x(); }
+function strictCaller(x) { "use strict"; return x(); }
+shouldBe("nonStrictCaller(nonStrictCallee)", "nonStrictCaller");
+shouldThrow("nonStrictCaller(strictCallee)", '"TypeError: Type error"');
+shouldThrow("strictCaller(nonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictCaller(strictCallee)", '"TypeError: Type error"');
+
+// .caller within a bound function reaches the caller, ignoring the binding.
+var boundNonStrictCallee = nonStrictCallee.bind();
+var boundStrictCallee = strictCallee.bind();
+shouldBe("nonStrictCaller(boundNonStrictCallee)", "nonStrictCaller");
+shouldThrow("nonStrictCaller(boundStrictCallee)", '"TypeError: Type error"');
+shouldThrow("strictCaller(boundNonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictCaller(boundStrictCallee)", '"TypeError: Type error"');
+
+// Check that .caller works (or throws) as expected, over an accessor call.
+function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get; }
+function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set; }
+var nonStrictAccessor = {
+ get foo() { return getFooGetter(nonStrictAccessor).caller; },
+ set foo(x) { if (getFooSetter(nonStrictAccessor).caller !==x) throw false; }
+};
+var strictAccessor = {
+ get foo() { "use strict"; return getFooGetter(strictAccessor).caller; },
+ set foo(x) { "use strict"; if (getFooSetter(strictAccessor).caller !==x) throw false; }
+};
+function nonStrictGetter(x) { return x.foo; }
+function nonStrictSetter(x) { x.foo = nonStrictSetter; return true; }
+function strictGetter(x) { "use strict"; return x.foo; }
+function strictSetter(x) { "use strict"; x.foo = nonStrictSetter; return true; }
+shouldBe("nonStrictGetter(nonStrictAccessor)", "nonStrictGetter");
+shouldBeTrue("nonStrictSetter(nonStrictAccessor)");
+shouldThrow("nonStrictGetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("nonStrictSetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("strictGetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictSetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictGetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("strictSetter(strictAccessor)", '"TypeError: Type error"');
Modified: trunk/LayoutTests/fast/js/stack-trace-expected.txt (109460 => 109461)
--- trunk/LayoutTests/fast/js/stack-trace-expected.txt 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/stack-trace-expected.txt 2012-03-02 00:12:58 UTC (rev 109461)
@@ -12,12 +12,16 @@
0 inner at stack-trace.js:28
1 at eval code
2 eval at [native code]
+ 3 evaler at stack-trace.js:29
+ 4 global code at stack-trace.js:39
--> Stack Trace:
0 inner at stack-trace.js:28
1 outer at stack-trace.js:27
2 at eval code
3 eval at [native code]
+ 4 evaler at stack-trace.js:29
+ 5 global code at stack-trace.js:40
--> Stack Trace:
0 inner at stack-trace.js:28
@@ -251,6 +255,103 @@
0 selfRecursive3 at stack-trace.js:69
1 at eval code
2 eval at [native code]
+ 3 selfRecursive3 at stack-trace.js:69
+ 4 at eval code
+ 5 eval at [native code]
+ 6 selfRecursive3 at stack-trace.js:69
+ 7 at eval code
+ 8 eval at [native code]
+ 9 selfRecursive3 at stack-trace.js:69
+ 10 at eval code
+ 11 eval at [native code]
+ 12 selfRecursive3 at stack-trace.js:69
+ 13 at eval code
+ 14 eval at [native code]
+ 15 selfRecursive3 at stack-trace.js:69
+ 16 at eval code
+ 17 eval at [native code]
+ 18 selfRecursive3 at stack-trace.js:69
+ 19 at eval code
+ 20 eval at [native code]
+ 21 selfRecursive3 at stack-trace.js:69
+ 22 at eval code
+ 23 eval at [native code]
+ 24 selfRecursive3 at stack-trace.js:69
+ 25 at eval code
+ 26 eval at [native code]
+ 27 selfRecursive3 at stack-trace.js:69
+ 28 at eval code
+ 29 eval at [native code]
+ 30 selfRecursive3 at stack-trace.js:69
+ 31 at eval code
+ 32 eval at [native code]
+ 33 selfRecursive3 at stack-trace.js:69
+ 34 at eval code
+ 35 eval at [native code]
+ 36 selfRecursive3 at stack-trace.js:69
+ 37 at eval code
+ 38 eval at [native code]
+ 39 selfRecursive3 at stack-trace.js:69
+ 40 at eval code
+ 41 eval at [native code]
+ 42 selfRecursive3 at stack-trace.js:69
+ 43 at eval code
+ 44 eval at [native code]
+ 45 selfRecursive3 at stack-trace.js:69
+ 46 at eval code
+ 47 eval at [native code]
+ 48 selfRecursive3 at stack-trace.js:69
+ 49 at eval code
+ 50 eval at [native code]
+ 51 selfRecursive3 at stack-trace.js:69
+ 52 at eval code
+ 53 eval at [native code]
+ 54 selfRecursive3 at stack-trace.js:69
+ 55 at eval code
+ 56 eval at [native code]
+ 57 selfRecursive3 at stack-trace.js:69
+ 58 at eval code
+ 59 eval at [native code]
+ 60 selfRecursive3 at stack-trace.js:69
+ 61 at eval code
+ 62 eval at [native code]
+ 63 selfRecursive3 at stack-trace.js:69
+ 64 at eval code
+ 65 eval at [native code]
+ 66 selfRecursive3 at stack-trace.js:69
+ 67 at eval code
+ 68 eval at [native code]
+ 69 selfRecursive3 at stack-trace.js:69
+ 70 at eval code
+ 71 eval at [native code]
+ 72 selfRecursive3 at stack-trace.js:69
+ 73 at eval code
+ 74 eval at [native code]
+ 75 selfRecursive3 at stack-trace.js:69
+ 76 at eval code
+ 77 eval at [native code]
+ 78 selfRecursive3 at stack-trace.js:69
+ 79 at eval code
+ 80 eval at [native code]
+ 81 selfRecursive3 at stack-trace.js:69
+ 82 at eval code
+ 83 eval at [native code]
+ 84 selfRecursive3 at stack-trace.js:69
+ 85 at eval code
+ 86 eval at [native code]
+ 87 selfRecursive3 at stack-trace.js:69
+ 88 at eval code
+ 89 eval at [native code]
+ 90 selfRecursive3 at stack-trace.js:69
+ 91 at eval code
+ 92 eval at [native code]
+ 93 selfRecursive3 at stack-trace.js:69
+ 94 at eval code
+ 95 eval at [native code]
+ 96 selfRecursive3 at stack-trace.js:69
+ 97 at eval code
+ 98 eval at [native code]
+ 99 selfRecursive3 at stack-trace.js:69
--> Stack Trace:
0 throwError at stack-trace.js:77
@@ -262,6 +363,7 @@
6 makeInlinableCall at stack-trace.js:131
7 g at stack-trace.js:140
8 map at [native code]
+ 9 global code at stack-trace.js:143
--> Stack Trace:
0 throwError at stack-trace.js:77
@@ -272,6 +374,7 @@
5 makeInlinableCall at stack-trace.js:131
6 g at stack-trace.js:140
7 map at [native code]
+ 8 global code at stack-trace.js:143
--> Stack Trace:
0 throwError at stack-trace.js:77
@@ -282,6 +385,7 @@
5 makeInlinableCall at stack-trace.js:131
6 g at stack-trace.js:140
7 map at [native code]
+ 8 global code at stack-trace.js:143
--> Stack Trace:
0 throwError at stack-trace.js:77
@@ -293,19 +397,27 @@
6 makeInlinableCall at stack-trace.js:131
7 g at stack-trace.js:140
8 map at [native code]
+ 9 global code at stack-trace.js:143
--> Stack Trace:
0 h at stack-trace.js:151
1 map at [native code]
+ 2 mapTest at stack-trace.js:158
+ 3 mapTestDriver at stack-trace.js:164
+ 4 global code at stack-trace.js:169
--> Stack Trace:
0 h at stack-trace.js:153
1 map at [native code]
+ 2 mapTest at stack-trace.js:158
+ 3 mapTestDriver at stack-trace.js:164
+ 4 global code at stack-trace.js:175
--> Stack Trace:
0 throwError at stack-trace.js:77
1 dfgFunction at stack-trace.js:184
2 map at [native code]
+ 3 global code at stack-trace.js:193
--> Stack Trace:
0 throwError at stack-trace.js:77
Modified: trunk/Source/_javascript_Core/ChangeLog (109460 => 109461)
--- trunk/Source/_javascript_Core/ChangeLog 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-03-02 00:12:58 UTC (rev 109461)
@@ -1,3 +1,22 @@
+2012-03-01 Gavin Barraclough <[email protected]>
+
+ ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
+ https://bugs.webkit.org/show_bug.cgi?id=80011
+
+ Reviewed by Oliver Hunt.
+
+ Also, fix getting the caller from within a bound function, for within a getter,
+ or setter (make our implementation match other browsers).
+
+ * interpreter/Interpreter.cpp:
+ (JSC::getCallerInfo):
+ - Allow this to get the caller of host functions.
+ (JSC::Interpreter::retrieveCallerFromVMCode):
+ - This should use getCallerInfo, and should skip over function bindings.
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::callerGetter):
+ - This should never return a strict-mode function.
+
2012-03-01 Yuqiang Xian <[email protected]>
DFG local CSE for a node can be terminated earlier
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (109460 => 109461)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-03-02 00:12:58 UTC (rev 109461)
@@ -44,6 +44,7 @@
#include "GetterSetter.h"
#include "JSActivation.h"
#include "JSArray.h"
+#include "JSBoundFunction.h"
#include "JSByteArray.h"
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
@@ -845,7 +846,7 @@
unsigned bytecodeOffset = 0;
lineNumber = -1;
ASSERT(!callFrame->hasHostCallFrameFlag());
- CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : 0;
+ CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
ASSERT(!callerFrame->hasHostCallFrameFlag());
@@ -5301,18 +5302,29 @@
JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
{
CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
+
if (!functionCallFrame)
return jsNull();
- if (functionCallFrame->callerFrame()->hasHostCallFrameFlag())
+ int lineNumber;
+ CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber);
+ if (!callerFrame)
return jsNull();
-
- CallFrame* callerFrame = functionCallFrame->trueCallerFrame();
-
JSValue caller = callerFrame->callee();
if (!caller)
return jsNull();
+ // Skip over function bindings.
+ ASSERT(caller.isObject());
+ while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
+ callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber);
+ if (!callerFrame)
+ return jsNull();
+ caller = callerFrame->callee();
+ if (!caller)
+ return jsNull();
+ }
+
return caller;
}
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (109460 => 109461)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2012-03-02 00:12:58 UTC (rev 109461)
@@ -181,7 +181,15 @@
{
JSFunction* thisObj = asFunction(slotBase);
ASSERT(!thisObj->isHostFunction());
- return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+ JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+
+ // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
+ if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
+ return caller;
+ JSFunction* function = asFunction(caller);
+ if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
+ return caller;
+ return throwTypeError(exec, "Function.caller used to retrieve strict caller");
}
JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)