Bug 1470558: Use Completion in Debugger.Object 'call' and 'apply' methods. r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Sun, 07 Jul 2019 09:47:51 +0000
changeset 544421 3800d671c64ee26d9f59a773488cc18a6da3587a
parent 544420 4f26d027343a0b26ddfb0410082bc2a46c3d9537
child 544422 483d687212fbf08e9b103c9b8565674b02fed827
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1470558
milestone69.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 1470558: Use Completion in Debugger.Object 'call' and 'apply' methods. r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D33078
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -11497,17 +11497,23 @@ bool DebuggerObject::callMethod(JSContex
     if (!args.growBy(callArgs.length() - 1)) {
       return false;
     }
     for (size_t i = 1; i < callArgs.length(); ++i) {
       args[i - 1].set(callArgs[i]);
     }
   }
 
-  return object->call(cx, object, thisv, args, callArgs.rval());
+  Rooted<Maybe<Completion>> completion(
+      cx, DebuggerObject::call(cx, object, thisv, args));
+  if (!completion.get()) {
+    return false;
+  }
+
+  return completion->buildCompletionValue(cx, object->owner(), callArgs.rval());
 }
 
 /* static */
 bool DebuggerObject::getPropertyMethod(JSContext* cx, unsigned argc,
                                        Value* vp) {
   THIS_DEBUGOBJECT(cx, argc, vp, "getProperty", args, object)
   Debugger* dbg = Debugger::fromChildJSObject(object);
 
@@ -11568,17 +11574,23 @@ bool DebuggerObject::applyMethod(JSConte
     }
     argc = unsigned(Min(argc, ARGS_LENGTH_MAX));
 
     if (!args.growBy(argc) || !GetElements(cx, argsobj, argc, args.begin())) {
       return false;
     }
   }
 
-  return object->call(cx, object, thisv, args, callArgs.rval());
+  Rooted<Maybe<Completion>> completion(
+      cx, DebuggerObject::call(cx, object, thisv, args));
+  if (!completion.get()) {
+    return false;
+  }
+
+  return completion->buildCompletionValue(cx, object->owner(), callArgs.rval());
 }
 
 static void EnterDebuggeeObjectRealm(JSContext* cx, Maybe<AutoRealm>& ar,
                                      JSObject* referent) {
   // |referent| may be a cross-compartment wrapper and CCWs normally
   // shouldn't be used with AutoRealm, but here we use an arbitrary realm for
   // now because we don't really have another option.
   ar.emplace(cx, referent->maybeCCWRealm()->maybeGlobal());
@@ -12557,81 +12569,84 @@ Result<Completion> DebuggerObject::setPr
   ObjectOpResult opResult;
   bool ok = SetProperty(cx, referent, id, value, receiver, opResult);
 
   return Completion::fromJSResult(cx, ok,
                                   BooleanValue(ok && opResult.reallyOk()));
 }
 
 /* static */
-bool DebuggerObject::call(JSContext* cx, HandleDebuggerObject object,
-                          HandleValue thisv_, Handle<ValueVector> args,
-                          MutableHandleValue result) {
+Maybe<Completion> DebuggerObject::call(JSContext* cx,
+                                       HandleDebuggerObject object,
+                                       HandleValue thisv_,
+                                       Handle<ValueVector> args) {
   RootedObject referent(cx, object->referent());
   Debugger* dbg = object->owner();
 
   if (!referent->isCallable()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_INCOMPATIBLE_PROTO, "Debugger.Object",
                               "call", referent->getClass()->name);
-    return false;
+    return Nothing();
   }
 
   RootedValue calleev(cx, ObjectValue(*referent));
 
   // Unwrap Debugger.Objects. This happens in the debugger's compartment since
   // that is where any exceptions must be reported.
   RootedValue thisv(cx, thisv_);
   if (!dbg->unwrapDebuggeeValue(cx, &thisv)) {
-    return false;
+    return Nothing();
   }
   Rooted<ValueVector> args2(cx, ValueVector(cx));
   if (!args2.append(args.begin(), args.end())) {
-    return false;
+    return Nothing();
   }
   for (unsigned i = 0; i < args2.length(); ++i) {
     if (!dbg->unwrapDebuggeeValue(cx, args2[i])) {
-      return false;
+      return Nothing();
     }
   }
 
   // Enter the debuggee compartment and rewrap all input value for that
   // compartment. (Rewrapping always takes place in the destination
   // compartment.)
   Maybe<AutoRealm> ar;
   EnterDebuggeeObjectRealm(cx, ar, referent);
   if (!cx->compartment()->wrap(cx, &calleev) ||
       !cx->compartment()->wrap(cx, &thisv)) {
-    return false;
+    return Nothing();
   }
   for (unsigned i = 0; i < args2.length(); ++i) {
     if (!cx->compartment()->wrap(cx, args2[i])) {
-      return false;
-    }
-  }
-
-  // Call the function. Use receiveCompletionValue to return to the debugger
-  // compartment and populate args.rval().
+      return Nothing();
+    }
+  }
+
+  // Call the function.
   LeaveDebuggeeNoExecute nnx(cx);
 
+  RootedValue result(cx);
   bool ok;
   {
     InvokeArgs invokeArgs(cx);
 
     ok = invokeArgs.init(cx, args2.length());
     if (ok) {
       for (size_t i = 0; i < args2.length(); ++i) {
         invokeArgs[i].set(args2[i]);
       }
 
-      ok = js::Call(cx, calleev, thisv, invokeArgs, result);
-    }
-  }
-
-  return dbg->receiveCompletionValue(ar, ok, result, result);
+      ok = js::Call(cx, calleev, thisv, invokeArgs, &result);
+    }
+  }
+
+  Rooted<Completion> completion(cx, Completion::fromJSResult(cx, ok, result));
+  ar.reset();
+  return Some(std::move(completion.get()));
 }
 
 /* static */
 bool DebuggerObject::forceLexicalInitializationByName(
     JSContext* cx, HandleDebuggerObject object, HandleId id, bool& result) {
   if (!JSID_IS_STRING(id)) {
     JS_ReportErrorNumberASCII(
         cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -1864,19 +1864,19 @@ class DebuggerObject : public NativeObje
                                           HandleId id,
                                           Handle<PropertyDescriptor> desc);
   static MOZ_MUST_USE bool defineProperties(
       JSContext* cx, HandleDebuggerObject object, Handle<IdVector> ids,
       Handle<PropertyDescriptorVector> descs);
   static MOZ_MUST_USE bool deleteProperty(JSContext* cx,
                                           HandleDebuggerObject object,
                                           HandleId id, ObjectOpResult& result);
-  static MOZ_MUST_USE bool call(JSContext* cx, HandleDebuggerObject object,
-                                HandleValue thisv, Handle<ValueVector> args,
-                                MutableHandleValue result);
+  static MOZ_MUST_USE mozilla::Maybe<Completion> call(
+      JSContext* cx, HandleDebuggerObject object, HandleValue thisv,
+      Handle<ValueVector> args);
   static MOZ_MUST_USE bool forceLexicalInitializationByName(
       JSContext* cx, HandleDebuggerObject object, HandleId id, bool& result);
   static MOZ_MUST_USE JS::Result<Completion> executeInGlobal(
       JSContext* cx, HandleDebuggerObject object,
       mozilla::Range<const char16_t> chars, HandleObject bindings,
       const EvalOptions& options);
   static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx,
                                              HandleDebuggerObject object,