Bug 694454 - Make Function.caller skip over eval frames rather than cause stack-walking code to snarl into a loop on them. r=luke, r=bhackett
authorJeff Walden <jwalden@mit.edu>
Thu, 13 Oct 2011 17:21:56 -0700
changeset 78784 dc36ba010aa67ea6b65e852f6421a20f4e0dd335
parent 78783 15d3df58e1e4e07efb9713699e956d15e9a50f40
child 78785 09242b2aa9898862465b7487b292195d3ee068e8
push id2684
push userjwalden@mit.edu
push dateFri, 14 Oct 2011 18:30:04 +0000
treeherdermozilla-inbound@68a211dccf2c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, bhackett
bugs694454
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 694454 - Make Function.caller skip over eval frames rather than cause stack-walking code to snarl into a loop on them. r=luke, r=bhackett
js/src/jsfun.cpp
js/src/tests/ecma_5/extensions/function-caller-skips-eval-frames.js
js/src/tests/ecma_5/extensions/jstests.list
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1299,17 +1299,17 @@ fun_getProperty(JSContext *cx, JSObject 
     /* Set to early to null in case of error */
     vp->setNull();
 
     /* Find fun's top-most activation record. */
     StackFrame *fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE);
     if (!fp)
         return true;
 
-    while (!fp->isFunctionFrame() || fp->fun() != fun) {
+    while (!fp->isFunctionFrame() || fp->fun() != fun || fp->isEvalFrame()) {
         fp = fp->prev();
         if (!fp)
             return true;
     }
 
 #ifdef JS_METHODJIT
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
         /*
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/function-caller-skips-eval-frames.js
@@ -0,0 +1,34 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+function innermost() { return arguments.callee.caller; }
+function nest() { return eval("innermost();"); }
+function nest2() { return nest(); }
+
+assertEq(nest2(), nest);
+
+var innermost = function innermost() { return arguments.callee.caller.caller; };
+
+assertEq(nest2(), nest2);
+
+function nestTwice() { return eval("eval('innermost();');"); }
+var nest = nestTwice;
+
+assertEq(nest2(), nest2);
+
+function innermostEval() { return eval("arguments.callee.caller"); }
+var innermost = innermostEval;
+
+assertEq(nest2(), nestTwice);
+
+function innermostEvalTwice() { return eval('eval("arguments.callee.caller");'); }
+var innermost = innermostEvalTwice;
+
+assertEq(nest2(), nestTwice);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
--- a/js/src/tests/ecma_5/extensions/jstests.list
+++ b/js/src/tests/ecma_5/extensions/jstests.list
@@ -9,16 +9,17 @@ script String-toSource.js
 script bug352085.js
 script bug472534.js
 script bug496985.js
 script bug566661.js
 script array-toString-recursion.js
 skip-if(!xulRuntime.shell) script cross-global-eval-is-indirect.js # needs newGlobal()
 script eval-native-callback-is-indirect.js
 script extension-methods-reject-null-undefined-this.js
+script function-caller-skips-eval-frames.js
 skip-if(!xulRuntime.shell) script function-definition-with.js # needs evaluate()
 script function-properties.js
 script getOwnPropertyNames-__proto__.js
 script iterator-in-catch.js
 script JSON-string-replacer-overflow.js
 skip-if(!xulRuntime.shell) script legacy-JSON.js # needs parseLegacyJSON
 fails script nested-delete-name-in-evalcode.js # bug 604301, at a minimum
 script proxy-strict.js