Bug 785174: Refactor DebuggerFrameEval to be useful for Debugger.Object.prototype.evalInGlobal{,WithBindings} r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Fri, 07 Sep 2012 20:08:14 -0700
changeset 104639 4afed1cd79a61e26763bfd581d581f79eae7c590
parent 104638 f083c0a666d3b82d776ed054568f48415635710f
child 104640 955f71c08edbc3709394d26bedd663639d88757a
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjorendorff
bugs785174
milestone18.0a1
Bug 785174: Refactor DebuggerFrameEval to be useful for Debugger.Object.prototype.evalInGlobal{,WithBindings} r=jorendorff
js/src/vm/Debugger.cpp
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3419,48 +3419,44 @@ js::EvaluateInEnv(JSContext *cx, Handle<
                                                     /* source = */ NULL, /* staticLimit = */ 1));
     if (!script)
         return false;
 
     script->isActiveEval = true;
     return ExecuteKernel(cx, script, *env, fp->thisValue(), EXECUTE_DEBUG, fp, rval);
 }
 
-enum EvalBindingsMode { WithoutBindings, WithBindings };
-
 static JSBool
-DebuggerFrameEval(JSContext *cx, unsigned argc, Value *vp, EvalBindingsMode mode)
+DebuggerGenericEval(JSContext *cx, const char *fullMethodName,
+                    const Value &code, Value *bindings, Value *vp,
+                    Debugger *dbg, HandleObject scope, StackFrame *fp)
 {
-    if (mode == WithBindings)
-        REQUIRE_ARGC("Debugger.Frame.evalWithBindings", 2);
-    else
-        REQUIRE_ARGC("Debugger.Frame.eval", 1);
-    THIS_FRAME(cx, argc, vp, mode == WithBindings ? "evalWithBindings" : "eval",
-               args, thisobj, fp);
-    Debugger *dbg = Debugger::fromChildJSObject(thisobj);
+    /* Either we're specifying the frame, or a global. */
+    JS_ASSERT_IF(fp, !scope);
+    JS_ASSERT_IF(!fp, scope && scope->isGlobal());
 
     /* Check the first argument, the eval code string. */
-    if (!args[0].isString()) {
+    if (!code.isString()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
-                             "Debugger.Frame.eval", "string", InformalValueTypeName(args[0]));
+                             fullMethodName, "string", InformalValueTypeName(code));
         return false;
     }
-    Rooted<JSLinearString*> linearStr(cx, args[0].toString()->ensureLinear(cx));
+    Rooted<JSLinearString*> linearStr(cx, code.toString()->ensureLinear(cx));
     if (!linearStr)
         return false;
 
     /*
      * Gather keys and values of bindings, if any. This must be done in the
      * debugger compartment, since that is where any exceptions must be
      * thrown.
      */
     AutoIdVector keys(cx);
     AutoValueVector values(cx);
-    if (mode == WithBindings) {
-        RootedObject bindingsobj(cx, NonNullObject(cx, args[1]));
+    if (bindings) {
+        RootedObject bindingsobj(cx, NonNullObject(cx, *bindings));
         if (!bindingsobj ||
             !GetPropertyNames(cx, bindingsobj, JSITER_OWNONLY, &keys) ||
             !values.growBy(keys.length()))
         {
             return false;
         }
         for (size_t i = 0; i < keys.length(); i++) {
             HandleId keyp = HandleId::fromMarkedLocation(&keys[i]);
@@ -3476,17 +3472,17 @@ DebuggerFrameEval(JSContext *cx, unsigne
     Maybe<AutoCompartment> ac;
     ac.construct(cx, fp->scopeChain());
 
     Rooted<Env *> env(cx, GetDebugScopeForFrame(cx, fp));
     if (!env)
         return false;
 
     /* If evalWithBindings, create the inner environment. */
-    if (mode == WithBindings) {
+    if (bindings) {
         /* TODO - This should probably be a Call object, like ES5 strict eval. */
         env = NewObjectWithGivenProto(cx, &ObjectClass, NULL, env);
         if (!env)
             return false;
         RootedId id(cx);
         for (size_t i = 0; i < keys.length(); i++) {
             id = keys[i];
             MutableHandleValue val = MutableHandleValue::fromMarkedLocation(&values[i]);
@@ -3504,23 +3500,31 @@ DebuggerFrameEval(JSContext *cx, unsigne
     bool ok = EvaluateInEnv(cx, env, fp, linearStr->chars(), linearStr->length(),
                             "debugger eval code", 1, &rval);
     return dbg->receiveCompletionValue(ac, ok, rval, vp);
 }
 
 static JSBool
 DebuggerFrame_eval(JSContext *cx, unsigned argc, Value *vp)
 {
-    return DebuggerFrameEval(cx, argc, vp, WithoutBindings);
+    THIS_FRAME(cx, argc, vp, "eval", args, thisobj, fp);
+    REQUIRE_ARGC("Debugger.Frame.prototype.eval", 1);
+    Debugger *dbg = Debugger::fromChildJSObject(thisobj);
+    return DebuggerGenericEval(cx, "Debugger.Frame.prototype.eval",
+                               args[0], NULL, vp, dbg, NullPtr(), fp);
 }
 
 static JSBool
 DebuggerFrame_evalWithBindings(JSContext *cx, unsigned argc, Value *vp)
 {
-    return DebuggerFrameEval(cx, argc, vp, WithBindings);
+    THIS_FRAME(cx, argc, vp, "evalWithBindings", args, thisobj, fp);
+    REQUIRE_ARGC("Debugger.Frame.prototype.evalWithBindings", 2);
+    Debugger *dbg = Debugger::fromChildJSObject(thisobj);
+    return DebuggerGenericEval(cx, "Debugger.Frame.prototype.evalWithBindings",
+                               args[0], &args[1], vp, dbg, NullPtr(), fp);
 }
 
 static JSBool
 DebuggerFrame_construct(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debugger.Frame");
     return false;
 }