Bug 1063330 - Remove the JS shell's evalInFrame. (r=jimb)
authorShu-yu Guo <shu@rfrn.org>
Thu, 13 Nov 2014 14:39:40 -0800
changeset 215678 f8e316fa65bb
parent 215677 1176cc3c3b34
child 215679 96a2f59f6ce4
push id27823
push usercbook@mozilla.com
push date2014-11-14 11:59 +0000
treeherdermozilla-central@bbb68df450c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs1063330
milestone36.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 1063330 - Remove the JS shell's evalInFrame. (r=jimb)
js/src/jit-test/lib/evalInFrame.js
js/src/jit-test/tests/auto-regress/bug765483.js
js/src/jit-test/tests/auto-regress/bug800878.js
js/src/jit-test/tests/basic/bug646968-7.js
js/src/jit-test/tests/basic/bug646968-8.js
js/src/jit-test/tests/basic/eif-generator.js
js/src/jit-test/tests/basic/testBug552248.js
js/src/jit-test/tests/basic/testBug663789-2.js
js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js
js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js
js/src/jit-test/tests/jaeger/bug563000/eif-call-typechange.js
js/src/jit-test/tests/jaeger/bug563000/eif-call.js
js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js
js/src/jit-test/tests/jaeger/bug563000/eif-getter-typechange.js
js/src/jit-test/tests/jaeger/bug563000/eif-getter.js
js/src/jit-test/tests/jaeger/bug563000/eif-global-newvar.js
js/src/jit-test/tests/jaeger/invokeSessionGuard.js
js/src/js.msg
js/src/shell/js.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/lib/evalInFrame.js
@@ -0,0 +1,32 @@
+var evalInFrame = (function (global) {
+  var dbgGlobal = newGlobal();
+  var dbg = new dbgGlobal.Debugger();
+
+  return function evalInFrame(upCount, code) {
+    dbg.addDebuggee(global);
+
+    // Skip ourself.
+    var frame = dbg.getNewestFrame().older;
+    for (var i = 0; i < upCount; i++) {
+      if (!frame.older)
+        break;
+      frame = frame.older;
+    }
+
+    var completion = frame.eval(code);
+    if (completion.return) {
+      var v = completion.return;
+      if (typeof v === "object")
+        v = v.unsafeDereference();
+      return v;
+    }
+    if (completion.throw) {
+      var v = completion.throw;
+      if (typeof v === "object")
+        v = v.unsafeDereference();
+      throw v;
+    }
+    if (completion === null)
+      terminate();
+  };
+})(this);
--- a/js/src/jit-test/tests/auto-regress/bug765483.js
+++ b/js/src/jit-test/tests/auto-regress/bug765483.js
@@ -1,16 +1,15 @@
 // |jit-test| error:ReferenceError;
 
 // Binary: cache/js-dbg-64-de23a9fc29db-linux
 // Flags: --ion-eager
 //
 
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 var obj1 = {}, obj2 = {};
 obj2['b'+i] = 0;
 for (var k in obj2) {
   (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'bound(f)', 'global-code'])", true); })();
 }
 for (var i = 0; i != array.length; ++i)
   array[i]();
--- a/js/src/jit-test/tests/auto-regress/bug800878.js
+++ b/js/src/jit-test/tests/auto-regress/bug800878.js
@@ -1,11 +1,13 @@
 // |jit-test| error:Error
 
 // Binary: cache/js-dbg-32-1301a72b1c39-linux
 // Flags: --ion-eager
 //
 
+load(libdir + "evalInFrame.js");
+
 [1,2,3,4,(':'),6,7,8].forEach(
     function(x) {
         assertEq(evalInFrame(0, ('^')), x);
     }
 );
--- a/js/src/jit-test/tests/basic/bug646968-7.js
+++ b/js/src/jit-test/tests/basic/bug646968-7.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function test(s) {
     eval(s);
     let (y = evalInFrame(0, '3'), x = x) {
 	assertEq(x, 5);
     }
 }
 test('var x = 5;');
--- a/js/src/jit-test/tests/basic/bug646968-8.js
+++ b/js/src/jit-test/tests/basic/bug646968-8.js
@@ -1,8 +1,7 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 var x = 5;
 let (x = eval("x++")) {
     assertEq(evalInFrame(0, "x"), 5);
 }
 assertEq(x, 6);
--- a/js/src/jit-test/tests/basic/eif-generator.js
+++ b/js/src/jit-test/tests/basic/eif-generator.js
@@ -1,12 +1,9 @@
-var global = newGlobal();
-var dbg = new global.Debugger(this);
-// Force dbg to observe all execution.
-dbg.onDebuggerStatement = function () {};
+load(libdir + "evalInFrame.js");
 
 function f() {
     let (x = 1) {
         while (true) {
             yield evalInFrame(0, "x");
             x++;
             let (y = 1) {
                 yield evalInFrame(0, "++y");
--- a/js/src/jit-test/tests/basic/testBug552248.js
+++ b/js/src/jit-test/tests/basic/testBug552248.js
@@ -1,12 +1,9 @@
-var global = newGlobal();
-var dbg = new global.Debugger(this);
-// Force dbg to observe all execution.
-dbg.onDebuggerStatement = function () {};
+load(libdir + "evalInFrame.js");
 
 var a = new Array();
 
 function i(save) {
     var x = 9;
     evalInFrame(0, "a.push(x)", save);
     evalInFrame(1, "a.push(z)", save);
     evalInFrame(2, "a.push(z)", save);
--- a/js/src/jit-test/tests/basic/testBug663789-2.js
+++ b/js/src/jit-test/tests/basic/testBug663789-2.js
@@ -1,7 +1,6 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 o = { toString:function() { return evalInFrame(1, "x") } }
 var x = 'C';
 var s = "aaaaaaaaaa".replace(/a/g, function() { var x = 'B'; return o });
 assertEq(s, "CCCCCCCCCC");
--- a/js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js
+++ b/js/src/jit-test/tests/basic/testEvalInFrameEdgeCase.js
@@ -1,10 +1,9 @@
-var global = newGlobal();
-var dbg = new global.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function g() {
     var x = 100;
     return evalInFrame(2, "x");
 }
 function f() {
     var x = 42;
     return evalInFrame.call(null, 0, "g()");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function callee() {
   evalInFrame(1, "var x = 'success'");
 }
 function caller(code) {
   eval(code);
   callee();
   return x;
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-call-typechange.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-call-typechange.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function callee() {
   evalInFrame(1, "x = 'success'");
 }
 function caller() {
   var x = ({ dana : "zuul" });
   callee();
   return x;
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-call.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-call.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function callee() {
   evalInFrame(1, "x = 'success'");
 }
 function caller() {
   var x = "failure";
   callee();
   return x;
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 this.__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
 function caller(obj) {
   var x = 'ignominy';
   obj.someProperty;
   return x;
 }
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-getter-typechange.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-getter-typechange.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 this.__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
 function caller(obj) {
   var x = ({ dana : 'zuul' });
   obj.someProperty;
   return x;
 }
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-getter.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-getter.js
@@ -1,10 +1,9 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 this.__defineGetter__("someProperty", function () { evalInFrame(1, "x = 'success'"); });
 function caller(obj) {
   var x = "failure";
   obj.someProperty;
   return x;
 }
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-global-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-global-newvar.js
@@ -1,8 +1,7 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
+load(libdir + "evalInFrame.js");
 
 function callee() {
   evalInFrame(1, "var x = 'success'");
 }
 callee();
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/invokeSessionGuard.js
+++ b/js/src/jit-test/tests/jaeger/invokeSessionGuard.js
@@ -1,11 +1,8 @@
-var g = newGlobal();
-var dbg = new g.Debugger(this);
-// Force dbg to observe all execution.
-dbg.onDebuggerStatement = function () {};
+load(libdir + "evalInFrame.js");
 
 [1,2,3,4,5,6,7,8].forEach(
     function(x) {
         // evalInFrame means lightweight gets call obj
         assertEq(evalInFrame(0, "x"), x);
     }
 );
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -85,17 +85,16 @@ MSG_DEF(JSMSG_INVALID_DESCRIPTOR,      0
 MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE,   1, JSEXN_TYPEERR, "{0} is not extensible")
 MSG_DEF(JSMSG_CANT_REDEFINE_PROP,      1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'")
 MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY,    0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
 MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
 MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
 MSG_DEF(JSMSG_BAD_GET_SET_FIELD,       1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
 MSG_DEF(JSMSG_THROW_TYPE_ERROR,        0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
 MSG_DEF(JSMSG_NOT_EXPECTED_TYPE,       3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
-MSG_DEF(JSMSG_NEED_DEBUG_MODE,         0, JSEXN_ERR, "function can be called only if a Debugger is observing all execution")
 MSG_DEF(JSMSG_NOT_ITERABLE,            1, JSEXN_TYPEERR, "{0} is not iterable")
 MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA,      2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one")
 MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
 MSG_DEF(JSMSG_WRONG_VALUE,             2, JSEXN_ERR, "expected {0} but found {1}")
 MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL,     1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
 MSG_DEF(JSMSG_INVALID_ARG_TYPE,        3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
 MSG_DEF(JSMSG_TERMINATED,              1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2633,80 +2633,16 @@ EvalInContext(JSContext *cx, unsigned ar
     }
 
     if (!cx->compartment()->wrap(cx, args.rval()))
         return false;
 
     return true;
 }
 
-static bool
-EvalInFrame(JSContext *cx, unsigned argc, jsval *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (!args.get(0).isInt32() || !args.get(1).isString()) {
-        JS_ReportError(cx, "Invalid arguments to evalInFrame");
-        return false;
-    }
-
-    uint32_t upCount = args[0].toInt32();
-    RootedString str(cx, args[1].toString());
-    bool saveCurrent = args.get(2).isBoolean() ? args[2].toBoolean() : false;
-
-    if (!cx->compartment()->debugObservesAllExecution()) {
-        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
-                                     nullptr, JSMSG_NEED_DEBUG_MODE);
-        return false;
-    }
-
-    /* Debug-mode currently disables Ion compilation. */
-    ScriptFrameIter fi(cx);
-    for (uint32_t i = 0; i < upCount; ++i, ++fi) {
-        ScriptFrameIter next(fi);
-        ++next;
-        if (next.done())
-            break;
-    }
-
-    AutoStableStringChars stableChars(cx);
-    if (!stableChars.initTwoByte(cx, str))
-        return JSTRAP_ERROR;
-
-    AbstractFramePtr frame = fi.abstractFramePtr();
-    RootedScript fpscript(cx, frame.script());
-
-    RootedObject scope(cx);
-    {
-        RootedObject scopeChain(cx, frame.scopeChain());
-        AutoCompartment ac(cx, scopeChain);
-        scope = GetDebugScopeForFrame(cx, frame, fi.pc());
-    }
-    Rooted<Env*> env(cx, scope);
-    if (!env)
-        return false;
-
-    if (!ComputeThis(cx, frame))
-        return false;
-    RootedValue thisv(cx, frame.thisValue());
-
-    AutoSaveFrameChain sfc(cx);
-    if (saveCurrent) {
-        if (!sfc.save())
-            return false;
-    }
-
-    bool ok;
-    {
-        AutoCompartment ac(cx, env);
-        ok = EvaluateInEnv(cx, env, thisv, frame, stableChars.twoByteRange(), fpscript->filename(),
-                           PCToLineNumber(fpscript, fi.pc()), args.rval());
-    }
-    return ok;
-}
-
 struct WorkerInput
 {
     JSRuntime *runtime;
     char16_t *chars;
     size_t length;
 
     WorkerInput(JSRuntime *runtime, char16_t *chars, size_t length)
       : runtime(runtime), chars(chars), length(length)
@@ -4409,21 +4345,16 @@ static const JSFunctionSpecWithHelp shel
 "  Get script line extent."),
 
     JS_FN_HELP("evalcx", EvalInContext, 1, 0,
 "evalcx(s[, o])",
 "  Evaluate s in optional sandbox object o.\n"
 "  if (s == '' && !o) return new o with eager standard classes\n"
 "  if (s == 'lazy' && !o) return new o with lazy standard classes"),
 
-    JS_FN_HELP("evalInFrame", EvalInFrame, 2, 0,
-"evalInFrame(n,str,save)",
-"  Evaluate 'str' in the nth up frame.\n"
-"  If 'save' (default false), save the frame chain."),
-
     JS_FN_HELP("evalInWorker", EvalInWorker, 1, 0,
 "evalInWorker(str)",
 "  Evaluate 'str' in a separate thread with its own runtime.\n"),
 
     JS_FN_HELP("shapeOf", ShapeOf, 1, 0,
 "shapeOf(obj)",
 "  Get the shape of obj (an implementation detail)."),