Bug 1470558: Use Completion in Debugger.Object 'call' and 'apply' methods. r=jorendorff
☠☠ backed out by 6a41c5908998 ☠ ☠
authorJim Blandy <jimb@mozilla.com>
Sat, 06 Jul 2019 21:26:45 +0000
changeset 544410 ef67e1b47f9cf2541784350a1bd5f322577b2e2c
parent 544409 6034237161dc0d87b74bfb7bc6551778d2a299ea
child 544411 1a18ccfcdc98eec64d8f76850713f0348cd073e5
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,