Bug 1527413 part 1. Give JSIterateCompartmentCallback a return value that can be used to stop the iteration. r=jandem
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 13 Feb 2019 14:10:19 +0000
changeset 458890 4ad4542bccee
parent 458889 81a368ce3847
child 458891 6c10cc59703a
push id35551
push usershindli@mozilla.com
push dateWed, 13 Feb 2019 21:34:09 +0000
treeherdermozilla-central@08f794a4928e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1527413
milestone67.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 1527413 part 1. Give JSIterateCompartmentCallback a return value that can be used to stop the iteration. r=jandem Differential Revision: https://phabricator.services.mozilla.com/D19559
js/src/gc/PublicIterators.cpp
js/src/jsapi.h
js/xpconnect/src/XPCWrappedJS.cpp
--- a/js/src/gc/PublicIterators.cpp
+++ b/js/src/gc/PublicIterators.cpp
@@ -215,17 +215,20 @@ void js::IterateGrayObjectsUnderCC(Zone*
 }
 
 JS_PUBLIC_API void JS_IterateCompartments(
     JSContext* cx, void* data,
     JSIterateCompartmentCallback compartmentCallback) {
   AutoTraceSession session(cx->runtime());
 
   for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
-    (*compartmentCallback)(cx, data, c);
+    if ((*compartmentCallback)(cx, data, c) ==
+        JS::CompartmentIterResult::Stop) {
+      break;
+    }
   }
 }
 
 JS_PUBLIC_API void JS::IterateRealms(JSContext* cx, void* data,
                                      JS::IterateRealmCallback realmCallback) {
   AutoTraceSession session(cx->runtime());
 
   Rooted<Realm*> realm(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -565,23 +565,32 @@ extern JS_PUBLIC_API void IterateRealmsW
  * Like IterateRealms, but only iterates realms in |compartment|.
  */
 extern JS_PUBLIC_API void IterateRealmsInCompartment(
     JSContext* cx, JS::Compartment* compartment, void* data,
     IterateRealmCallback realmCallback);
 
 }  // namespace JS
 
-typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data,
-                                             JS::Compartment* compartment);
+/**
+ * An enum that JSIterateCompartmentCallback can return to indicate
+ * whether to keep iterating.
+ */
+namespace JS {
+enum class CompartmentIterResult { KeepGoing, Stop };
+}  // namespace JS
+
+typedef JS::CompartmentIterResult (*JSIterateCompartmentCallback)(
+    JSContext* cx, void* data, JS::Compartment* compartment);
 
 /**
- * This function calls |compartmentCallback| on every compartment. Beware that
- * there is no guarantee that the compartment will survive after the callback
- * returns. Also, barriers are disabled via the TraceSession.
+ * This function calls |compartmentCallback| on every compartment until either
+ * all compartments have been iterated or CompartmentIterResult::Stop is
+ * returned. Beware that there is no guarantee that the compartment will survive
+ * after the callback returns. Also, barriers are disabled via the TraceSession.
  */
 extern JS_PUBLIC_API void JS_IterateCompartments(
     JSContext* cx, void* data,
     JSIterateCompartmentCallback compartmentCallback);
 
 /**
  * Mark a jsid after entering a new compartment. Different zones separately
  * mark the ids in a runtime, and this must be used any time an id is obtained
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -457,21 +457,22 @@ void XPCJSRuntime::RemoveWrappedJS(nsXPC
            ->HasWrapper(wrapper));
   GetMultiCompartmentWrappedJSMap()->Remove(wrapper);
   xpc::CompartmentPrivate::Get(wrapper->GetJSObjectPreserveColor())
       ->GetWrappedJSMap()
       ->Remove(wrapper);
 }
 
 #ifdef DEBUG
-static void NotHasWrapperAssertionCallback(JSContext* cx, void* data,
-                                           JS::Compartment* comp) {
+static JS::CompartmentIterResult NotHasWrapperAssertionCallback(
+    JSContext* cx, void* data, JS::Compartment* comp) {
   auto wrapper = static_cast<nsXPCWrappedJS*>(data);
   auto xpcComp = xpc::CompartmentPrivate::Get(comp);
   MOZ_ASSERT_IF(xpcComp, !xpcComp->GetWrappedJSMap()->HasWrapper(wrapper));
+  return JS::CompartmentIterResult::KeepGoing;
 }
 #endif
 
 void XPCJSRuntime::AssertInvalidWrappedJSNotInTable(
     nsXPCWrappedJS* wrapper) const {
 #ifdef DEBUG
   if (!wrapper->IsValid()) {
     MOZ_ASSERT(!GetMultiCompartmentWrappedJSMap()->HasWrapper(wrapper));