Bug 1271653 - Implement a C++ interface for executeInGlobal(WithBindings);r=jimb
☠☠ backed out by 44d2dae11890 ☠ ☠
authorEddy Bruel <ejpbruel@mozilla.com>
Tue, 31 May 2016 14:14:31 +0200
changeset 338690 11c4daf94661a3e5a8d775827468167857e1b5b1
parent 338689 b11a57f5b70bdf57cf2febf53eec719ec1072963
child 338691 f59d802ab85747c1e4c8b475e3680de611fd2a54
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs1271653
milestone49.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 1271653 - Implement a C++ interface for executeInGlobal(WithBindings);r=jimb
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -418,29 +418,16 @@ ValueToStableChars(JSContext* cx, const 
     RootedLinearString linear(cx, value.toString()->ensureLinear(cx));
     if (!linear)
         return false;
     if (!stableChars.initTwoByte(cx, linear))
         return false;
     return true;
 }
 
-class MOZ_RAII EvalOptions {
-    const char* filename_;
-    unsigned lineno_;
-
-  public:
-    EvalOptions() : filename_(nullptr), lineno_(1) {}
-    ~EvalOptions();
-    const char* filename() const { return filename_; }
-    unsigned lineno() const { return lineno_; }
-    bool setFilename(JSContext* cx, const char* filename);
-    void setLineno(unsigned lineno) { lineno_ = lineno; }
-};
-
 EvalOptions::~EvalOptions()
 {
     js_free(const_cast<char*>(filename_));
 }
 
 bool
 EvalOptions::setFilename(JSContext* cx, const char* filename)
 {
@@ -487,16 +474,52 @@ ParseEvalOptions(JSContext* cx, HandleVa
         if (!ToUint32(cx, v, &lineno))
             return false;
         options.setLineno(lineno);
     }
 
     return true;
 }
 
+static bool
+RequireGlobalObject(JSContext* cx, HandleValue dbgobj, HandleObject referent)
+{
+    RootedObject obj(cx, referent);
+
+    if (!obj->is<GlobalObject>()) {
+        const char* isWrapper = "";
+        const char* isWindowProxy = "";
+
+        /* Help the poor programmer by pointing out wrappers around globals... */
+        if (obj->is<WrapperObject>()) {
+            obj = js::UncheckedUnwrap(obj);
+            isWrapper = "a wrapper around ";
+        }
+
+        /* ... and WindowProxies around Windows. */
+        if (IsWindowProxy(obj)) {
+            obj = ToWindowIfWindowProxy(obj);
+            isWindowProxy = "a WindowProxy referring to ";
+        }
+
+        if (obj->is<GlobalObject>()) {
+            ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_WRAPPER_IN_WAY,
+                                  JSDVG_SEARCH_STACK, dbgobj, nullptr,
+                                  isWrapper, isWindowProxy);
+        } else {
+            ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_BAD_REFERENT,
+                                  JSDVG_SEARCH_STACK, dbgobj, nullptr,
+                                  "a global object", nullptr);
+        }
+        return false;
+    }
+
+    return true;
+}
+
 
 /*** Breakpoints *********************************************************************************/
 
 BreakpointSite::BreakpointSite(JSScript* script, jsbytecode* pc)
   : script(script), pc(pc), enabledCount(0)
 {
     MOZ_ASSERT(!script->hasBreakpointsAt(pc));
     JS_INIT_CLIST(&breakpoints);
@@ -8590,16 +8613,64 @@ DebuggerObject_apply(JSContext* cx, unsi
         if (!args.growBy(argc) || !GetElements(cx, argsobj, argc, args.begin()))
             return false;
     }
 
     return object->call(cx, object, thisv, args, callArgs.rval());
 }
 
 static bool
+DebuggerObject_executeInGlobal(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGOBJECT(cx, argc, vp, "executeInGlobal", args, object);
+    if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobal", 1))
+        return false;
+
+    AutoStableStringChars stableChars(cx);
+    if (!ValueToStableChars(cx, "Debugger.Object.prototype.executeInGlobal", args[0],
+                            stableChars))
+    {
+        return false;
+    }
+    mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
+
+    EvalOptions options;
+    if (!ParseEvalOptions(cx, args.get(1), options))
+        return false;
+
+    return DebuggerObject::executeInGlobal(cx, object, chars, nullptr, options, args.rval());
+}
+
+static bool
+DebuggerObject_executeInGlobalWithBindings(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGOBJECT(cx, argc, vp, "executeInGlobalWithBindings", args, object);
+    if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobalWithBindings", 2))
+        return false;
+
+    AutoStableStringChars stableChars(cx);
+    if (!ValueToStableChars(cx, "Debugger.Object.prototype.executeInGlobalWithBindings", args[0],
+                            stableChars))
+    {
+        return false;
+    }
+    mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
+
+    RootedObject bindings(cx, NonNullObject(cx, args[1]));
+    if (!bindings)
+        return false;
+
+    EvalOptions options;
+    if (!ParseEvalOptions(cx, args.get(2), options))
+        return false;
+
+    return DebuggerObject::executeInGlobal(cx, object, chars, bindings, options, args.rval());
+}
+
+static bool
 DebuggerObject_makeDebuggeeValue(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "makeDebuggeeValue", args, dbg, referent);
     if (!args.requireAtLeast(cx, "Debugger.Object.prototype.makeDebuggeeValue", 1))
         return false;
 
     RootedValue arg0(cx, args[0]);
 
@@ -8618,52 +8689,16 @@ DebuggerObject_makeDebuggeeValue(JSConte
         if (!dbg->wrapDebuggeeValue(cx, &arg0))
             return false;
     }
 
     args.rval().set(arg0);
     return true;
 }
 
-static bool
-RequireGlobalObject(JSContext* cx, HandleValue dbgobj, HandleObject referent)
-{
-    RootedObject obj(cx, referent);
-
-    if (!obj->is<GlobalObject>()) {
-        const char* isWrapper = "";
-        const char* isWindowProxy = "";
-
-        /* Help the poor programmer by pointing out wrappers around globals... */
-        if (obj->is<WrapperObject>()) {
-            obj = js::UncheckedUnwrap(obj);
-            isWrapper = "a wrapper around ";
-        }
-
-        /* ... and WindowProxies around Windows. */
-        if (IsWindowProxy(obj)) {
-            obj = ToWindowIfWindowProxy(obj);
-            isWindowProxy = "a WindowProxy referring to ";
-        }
-
-        if (obj->is<GlobalObject>()) {
-            ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_WRAPPER_IN_WAY,
-                                  JSDVG_SEARCH_STACK, dbgobj, nullptr,
-                                  isWrapper, isWindowProxy);
-        } else {
-            ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_BAD_REFERENT,
-                                  JSDVG_SEARCH_STACK, dbgobj, nullptr,
-                                  "a global object", nullptr);
-        }
-        return false;
-    }
-
-    return true;
-}
-
 // Lookup a binding on the referent's global scope and change it to undefined
 // if it is an uninitialized lexical, otherwise do nothing. The method's return
 // value is true _only_ when an uninitialized lexical has been altered, otherwise
 // it is false.
 bool
 DebuggerObject_forceLexicalInitializationByName(JSContext *cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "forceLexicalInitializationByname", args, referent);
@@ -8698,73 +8733,16 @@ DebuggerObject_forceLexicalInitializatio
             initialized = true;
         }
     }
     args.rval().setBoolean(initialized);
     return true;
 }
 
 static bool
-DebuggerObject_executeInGlobal(JSContext* cx, unsigned argc, Value* vp)
-{
-    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "executeInGlobal", args, dbg, referent);
-    if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobal", 1))
-        return false;
-    if (!RequireGlobalObject(cx, args.thisv(), referent))
-        return false;
-
-    AutoStableStringChars stableChars(cx);
-    if (!ValueToStableChars(cx, "Debugger.Object.prototype.executeInGlobal", args[0],
-                            stableChars))
-    {
-        return false;
-    }
-    mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
-
-    EvalOptions options;
-    if (!ParseEvalOptions(cx, args.get(1), options))
-        return false;
-
-    RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
-    return DebuggerGenericEval(cx, chars, nullptr, options, args.rval(), dbg, globalLexical,
-                               nullptr);
-}
-
-static bool
-DebuggerObject_executeInGlobalWithBindings(JSContext* cx, unsigned argc, Value* vp)
-{
-    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "executeInGlobalWithBindings", args, dbg,
-                                    referent);
-    if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobalWithBindings", 2))
-        return false;
-    if (!RequireGlobalObject(cx, args.thisv(), referent))
-        return false;
-
-    AutoStableStringChars stableChars(cx);
-    if (!ValueToStableChars(cx, "Debugger.Object.prototype.executeInGlobalWithBindings", args[0],
-                            stableChars))
-    {
-        return false;
-    }
-    mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
-
-    RootedObject bindings(cx, NonNullObject(cx, args[1]));
-    if (!bindings)
-        return false;
-
-    EvalOptions options;
-    if (!ParseEvalOptions(cx, args.get(2), options))
-        return false;
-
-    RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
-    return DebuggerGenericEval(cx, chars, bindings, options, args.rval(), dbg, globalLexical,
-                               nullptr);
-}
-
-static bool
 DebuggerObject_asEnvironment(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "asEnvironment", args, dbg, referent);
     if (!RequireGlobalObject(cx, args.thisv(), referent))
         return false;
 
     Rooted<Env*> env(cx);
     {
@@ -8862,19 +8840,19 @@ const JSFunctionSpec DebuggerObject::met
     JS_FN("preventExtensions", DebuggerObject_preventExtensions, 0, 0),
     JS_FN("seal", DebuggerObject_seal, 0, 0),
     JS_FN("freeze", DebuggerObject_freeze, 0, 0),
     JS_FN("defineProperty", DebuggerObject_defineProperty, 2, 0),
     JS_FN("defineProperties", DebuggerObject_defineProperties, 1, 0),
     JS_FN("deleteProperty", DebuggerObject_deleteProperty, 1, 0),
     JS_FN("call", DebuggerObject_call, 0, 0),
     JS_FN("apply", DebuggerObject_apply, 0, 0),
-    JS_FN("makeDebuggeeValue", DebuggerObject_makeDebuggeeValue, 1, 0),
     JS_FN("executeInGlobal", DebuggerObject_executeInGlobal, 1, 0),
     JS_FN("executeInGlobalWithBindings", DebuggerObject_executeInGlobalWithBindings, 2, 0),
+    JS_FN("makeDebuggeeValue", DebuggerObject_makeDebuggeeValue, 1, 0),
     JS_FN("asEnvironment", DebuggerObject_asEnvironment, 0, 0),
     JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
     JS_FN("unsafeDereference", DebuggerObject_unsafeDereference, 0, 0),
     JS_FS_END
 };
 
 /* static */ NativeObject*
 DebuggerObject::initClass(JSContext* cx, HandleObject obj, HandleObject debugCtor)
@@ -9197,16 +9175,33 @@ DebuggerObject::call(JSContext* cx, Hand
 
             ok = js::Call(cx, calleev, thisv, invokeArgs, result);
         }
     }
 
     return dbg->receiveCompletionValue(ac, ok, result, result);
 }
 
+/* static */ bool
+DebuggerObject::executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
+                                mozilla::Range<const char16_t> chars, HandleObject bindings,
+                                const EvalOptions& options, MutableHandleValue result)
+{
+    RootedObject referent(cx, object->referent());
+    Debugger* dbg = object->owner();
+
+    RootedValue dbgobj(cx, ObjectValue(*object));
+    if (!RequireGlobalObject(cx, dbgobj, referent))
+        return false;
+    RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
+
+    return DebuggerGenericEval(cx, chars, bindings, options, result, dbg, globalLexical,
+                               nullptr);
+}
+
 
 /*** Debugger.Environment ************************************************************************/
 
 void
 DebuggerEnv_trace(JSTracer* trc, JSObject* obj)
 {
     /*
      * There is a barrier on private pointers, so the Unbarriered marking
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -204,16 +204,29 @@ class AutoSuppressDebuggeeNoExecuteCheck
     }
 
     ~AutoSuppressDebuggeeNoExecuteChecks() {
         MOZ_ASSERT(!*stack_);
         *stack_ = prev_;
     }
 };
 
+class MOZ_RAII EvalOptions {
+    const char* filename_;
+    unsigned lineno_;
+
+  public:
+    EvalOptions() : filename_(nullptr), lineno_(1) {}
+    ~EvalOptions();
+    const char* filename() const { return filename_; }
+    unsigned lineno() const { return lineno_; }
+    bool setFilename(JSContext* cx, const char* filename);
+    void setLineno(unsigned lineno) { lineno_ = lineno; }
+};
+
 /*
  * Env is the type of what ES5 calls "lexical environments" (runtime activations
  * of lexical scopes). This is currently just JSObject, and is implemented by
  * CallObject, ClonedBlockObject, DynamicWithObject, and DeclEnvObject, among
  * others--but environments and objects are really two different concepts.
  */
 typedef JSObject Env;
 
@@ -1053,16 +1066,19 @@ class DebuggerObject : public NativeObje
                                Handle<PropertyDescriptor> desc);
     static bool defineProperties(JSContext* cx, Handle<DebuggerObject*> object,
                                  Handle<IdVector> ids,
                                  Handle<PropertyDescriptorVector> descs);
     static bool deleteProperty(JSContext* cx, Handle<DebuggerObject*> object, HandleId id,
                                ObjectOpResult& result);
     static bool call(JSContext* cx, Handle<DebuggerObject*> object, HandleValue thisv,
                      Handle<ValueVector> args, MutableHandleValue result);
+    static bool executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
+                                mozilla::Range<const char16_t> chars, HandleObject bindings,
+                                const EvalOptions& options, MutableHandleValue result);
 
   private:
     enum {
         OWNER_SLOT
     };
 
     static const unsigned RESERVED_SLOTS = 1;