Backed out 3 changesets (bug 956376) for browser_dbg-quick-open.js failures. a=backout
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 23 Aug 2018 15:15:31 +0300
changeset 488089 ddd5a54f6a52fecbb51a177f514f3cdf0d40caff
parent 488088 32c6c1848f149454182911c6635b42956cf719de
child 488090 22e0f5646bde4d96395d94c64c801bd58e35df42
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs956376
milestone63.0a1
backs out3e61a2874367c13ba2c5ec361a5633f7da153d45
8169bed1fafcecd6f78077a71af10b37df1af23b
46dfdfe140670b0ebcaad372df05065782fc9f56
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
Backed out 3 changesets (bug 956376) for browser_dbg-quick-open.js failures. a=backout Backed out changeset 3e61a2874367 (bug 956376) Backed out changeset 8169bed1fafc (bug 956376) Backed out changeset 46dfdfe14067 (bug 956376)
devtools/server/actors/promises.js
devtools/server/actors/thread.js
js/src/doc/Debugger/Debugger.md
js/src/jit-test/tests/debug/Debugger-findSources-01.js
js/src/jit-test/tests/debug/Debugger-findSources-02.js
js/src/jit-test/tests/debug/Debugger-findSources-03.js
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/devtools/server/actors/promises.js
+++ b/devtools/server/actors/promises.js
@@ -60,18 +60,18 @@ var PromisesActor = protocol.ActorClassW
     this.dbg.addDebuggees();
 
     this._navigationLifetimePool = this._createActorPool();
     this.conn.addActorPool(this._navigationLifetimePool);
 
     this._newPromises = [];
     this._promisesSettled = [];
 
-    this.dbg.findSources().forEach(source => {
-      this.parentActor.sources.createSourceActors(source);
+    this.dbg.findScripts().forEach(s => {
+      this.parentActor.sources.createSourceActors(s.source);
     });
 
     this.dbg.onNewScript = s => {
       this.parentActor.sources.createSourceActors(s.source);
     };
 
     EventEmitter.on(this.parentActor, "window-ready", this._onWindowReady);
 
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -1106,22 +1106,32 @@ const ThreadActor = ActorClassWithSpec(t
       } else if (actor.destroy) {
         actor.destroy();
       }
     }
     return res ? res : {};
   },
 
   /**
-   * Get the source lists from the debugger.
+   * Get the script and source lists from the debugger.
    */
   _discoverSources: function() {
-    const sources = this.dbg.findSources();
-    return Promise.all(sources.map(source => {
-      return this.sources.createSourceActors(source);
+    // Only get one script per Debugger.Source.
+    const sourcesToScripts = new Map();
+    const scripts = this.dbg.findScripts();
+
+    for (let i = 0, len = scripts.length; i < len; i++) {
+      const s = scripts[i];
+      if (s.source) {
+        sourcesToScripts.set(s.source, s);
+      }
+    }
+
+    return Promise.all([...sourcesToScripts.values()].map(script => {
+      return this.sources.createSourceActors(script.source);
     }));
   },
 
   onSources: function(request) {
     return this._discoverSources().then(() => {
       // No need to flush the new source packets here, as we are sending the
       // list of sources out immediately and we don't need to invoke the
       // overhead of an RDP packet for every source right now. Let the default
--- a/js/src/doc/Debugger/Debugger.md
+++ b/js/src/doc/Debugger/Debugger.md
@@ -352,20 +352,36 @@ other kinds of objects.
     debuggee globals, if a debuggee global is otherwise unreachable, it may
     be dropped at any moment from the array this method returns.
 
 `getNewestFrame()`
 :   Return a [`Debugger.Frame`][frame] instance referring to the youngest
     [visible frame][vf] currently on the calling thread's stack, or `null`
     if there are no visible frames on the stack.
 
-<code>findSources()</code>
-:   Return an array of all [`Debugger.Source`][source] instances of all debuggee
+<code>findSources([<i>query</i>]) <i>(not yet implemented)</i></code>
+:   Return an array of all [`Debugger.Source`][source] instances matching
+    <i>query</i>. Each source appears only once in the array. <i>Query</i>
+    is an object whose properties restrict which sources are returned; a
+    source must meet all the criteria given by <i>query</i> to be returned.
+    If <i>query</i> is omitted, we return all sources of all debuggee
     scripts.
 
+    <i>Query</i> may have the following properties:
+
+    `url`
+    :   The source's `url` property must be equal to this value.
+
+    `global`
+    :   The source must have been evaluated in the scope of the given global
+        object. If this property's value is a [`Debugger.Object`][object] instance
+        belonging to this `Debugger` instance, then its referent is used. If the
+        object is not a global object, then the global in whose scope it was
+        allocated is used.
+
     Note that the result may include sources that can no longer ever be
     used by the debuggee: say, eval code that has finished running, or
     source for unreachable functions. Whether such sources appear can be
     affected by the garbage collector's behavior, so this function's result
     is not entirely deterministic.
 
 <code>findScripts([<i>query</i>])</code>
 :   Return an array of [`Debugger.Script`][script] instances for all debuggee scripts
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debugger-findSources-01.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// In a debugger with no debuggees, findSources should return no scripts.
-
-const dbg = new Debugger;
-assertEq(dbg.findSources().length, 0);
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debugger-findSources-02.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// In a debugger with scripts, findSources finds the script source.
-
-const g = newGlobal();
-// Declare a function in order to keep the script source alive across GC.
-g.evaluate(`function fa() {}`, { fileName: "a.js" });
-g.evaluate(`function fb() {}`, { fileName: "b.js" });
-g.evaluate(`function fc() {}`, { fileName: "c.js" });
-
-const dbg = new Debugger();
-const gw = dbg.addDebuggee(g);
-
-const sources = dbg.findSources();
-assertEq(sources.filter(s => s.url == "a.js").length, 1);
-assertEq(sources.filter(s => s.url == "b.js").length, 1);
-assertEq(sources.filter(s => s.url == "c.js").length, 1);
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debugger-findSources-03.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// In a debugger with multiple debuggees, findSources finds script sources across all debuggees.
-
-const g1 = newGlobal();
-const g2 = newGlobal();
-// Declare a function in order to keep the script source alive across GC.
-g1.evaluate(`function fa() {}`, { fileName: "a.js" });
-g1.evaluate(`function fb() {}`, { fileName: "b.js" });
-g2.evaluate(`function fc() {}`, { fileName: "c.js" });
-g2.evaluate(`function fd() {}`, { fileName: "d.js" });
-
-const dbg = new Debugger();
-const g1w = dbg.addDebuggee(g1);
-const g2w = dbg.addDebuggee(g2);
-
-const sources = dbg.findSources();
-assertEq(dbg.findSources().filter(s => s.url == "a.js").length, 1);
-assertEq(dbg.findSources().filter(s => s.url == "b.js").length, 1);
-assertEq(dbg.findSources().filter(s => s.url == "c.js").length, 1);
-assertEq(dbg.findSources().filter(s => s.url == "d.js").length, 1);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4183,94 +4183,41 @@ Debugger::removeDebuggeeGlobal(FreeOp* f
         global->realm()->updateDebuggerObservesBinarySource();
         global->realm()->updateDebuggerObservesCoverage();
     }
 }
 
 
 static inline DebuggerSourceReferent GetSourceReferent(JSObject* obj);
 
-class MOZ_STACK_CLASS Debugger::QueryBase
-{
-  protected:
-    QueryBase(JSContext* cx, Debugger* dbg)
-      : cx(cx),
-        debugger(dbg),
-        iterMarker(&cx->runtime()->gc),
-        realms(cx->zone()),
-        oom(false)
-    {}
-
-    // The context in which we should do our work.
-    JSContext* cx;
-
-    // The debugger for which we conduct queries.
-    Debugger* debugger;
-
-    // Require the set of realms to stay fixed while this query is alive.
-    gc::AutoEnterIteration iterMarker;
-
-    using RealmSet = HashSet<Realm*, DefaultHasher<Realm*>, ZoneAllocPolicy>;
-
-    // A script must be in one of these realms to match the query.
-    RealmSet realms;
-
-    // Indicates whether OOM has occurred while matching.
-    bool oom;
-
-    bool addRealm(Realm* realm) {
-        return realms.put(realm);
-    }
-
-    // Arrange for this query to match only scripts that run in |global|.
-    bool matchSingleGlobal(GlobalObject* global) {
-        MOZ_ASSERT(realms.count() == 0);
-        if (!addRealm(global->realm())) {
-            ReportOutOfMemory(cx);
-            return false;
-        }
-        return true;
-    }
-
-    // Arrange for this ScriptQuery to match all scripts running in debuggee
-    // globals.
-    bool matchAllDebuggeeGlobals() {
-        MOZ_ASSERT(realms.count() == 0);
-        // Build our realm set from the debugger's set of debuggee globals.
-        for (WeakGlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
-            if (!addRealm(r.front()->realm())) {
-                ReportOutOfMemory(cx);
-                return false;
-            }
-        }
-        return true;
-    }
-};
-
 /*
  * A class for parsing 'findScripts' query arguments and searching for
  * scripts that match the criteria they represent.
  */
-class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase
+class MOZ_STACK_CLASS Debugger::ScriptQuery
 {
   public:
     /* Construct a ScriptQuery to use matching scripts for |dbg|. */
-    ScriptQuery(JSContext* cx, Debugger* dbg)
-      : QueryBase(cx, dbg),
+    ScriptQuery(JSContext* cx, Debugger* dbg):
+        cx(cx),
+        debugger(dbg),
+        iterMarker(&cx->runtime()->gc),
+        realms(cx->zone()),
         url(cx),
         displayURLString(cx),
         hasSource(false),
         source(cx, AsVariant(static_cast<ScriptSourceObject*>(nullptr))),
         hasLine(false),
         line(0),
         innermost(false),
         innermostForRealm(cx->zone()),
         scriptVector(cx, ScriptVector(cx)),
         lazyScriptVector(cx, LazyScriptVector(cx)),
-        wasmInstanceVector(cx, WasmInstanceObjectVector(cx))
+        wasmInstanceVector(cx, WasmInstanceObjectVector(cx)),
+        oom(false)
     {}
 
     /*
      * Parse the query object |query|, and prepare to match only the scripts
      * it specifies.
      */
     bool parseQuery(HandleObject query) {
         // Check for a 'global' property, which limits the results to those
@@ -4484,16 +4431,30 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
         return lazyScriptVector;
     }
 
     Handle<WasmInstanceObjectVector> foundWasmInstances() const {
         return wasmInstanceVector;
     }
 
   private:
+    /* The context in which we should do our work. */
+    JSContext* cx;
+
+    /* The debugger for which we conduct queries. */
+    Debugger* debugger;
+
+    /* Require the set of realms to stay fixed while the ScriptQuery is alive. */
+    gc::AutoEnterIteration iterMarker;
+
+    using RealmSet = HashSet<Realm*, DefaultHasher<Realm*>, ZoneAllocPolicy>;
+
+    /* A script must be in one of these realms to match the query. */
+    RealmSet realms;
+
     /* If this is a string, matching scripts have urls equal to it. */
     RootedValue url;
 
     /* url as a C string. */
     JSAutoByteString urlCString;
 
     /* If this is a string, matching scripts' sources have displayURLs equal to
      * it. */
@@ -4533,16 +4494,49 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
     Rooted<ScriptVector> scriptVector;
     Rooted<LazyScriptVector> lazyScriptVector;
 
     /*
      * Like above, but for wasm modules.
      */
     Rooted<WasmInstanceObjectVector> wasmInstanceVector;
 
+    /* Indicates whether OOM has occurred while matching. */
+    bool oom;
+
+    bool addRealm(Realm* realm) {
+        return realms.put(realm);
+    }
+
+    /* Arrange for this ScriptQuery to match only scripts that run in |global|. */
+    bool matchSingleGlobal(GlobalObject* global) {
+        MOZ_ASSERT(realms.count() == 0);
+        if (!addRealm(global->realm())) {
+            ReportOutOfMemory(cx);
+            return false;
+        }
+        return true;
+    }
+
+    /*
+     * Arrange for this ScriptQuery to match all scripts running in debuggee
+     * globals.
+     */
+    bool matchAllDebuggeeGlobals() {
+        MOZ_ASSERT(realms.count() == 0);
+        // Build our realm set from the debugger's set of debuggee globals.
+        for (WeakGlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
+            if (!addRealm(r.front()->realm())) {
+                ReportOutOfMemory(cx);
+                return false;
+            }
+        }
+        return true;
+    }
+
     /*
      * Given that parseQuery or omittedQuery has been called, prepare to match
      * scripts. Set urlCString and displayURLChars as appropriate.
      */
     bool prepareQuery() {
         // Compute urlCString and displayURLChars, if a url or displayURL was
         // given respectively.
         if (url.isString()) {
@@ -4767,170 +4761,16 @@ Debugger::findScripts(JSContext* cx, uns
         result->setDenseElement(wasmStart + i, ObjectValue(*scriptObject));
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
 /*
- * A class for searching sources for 'findSources'.
- */
-class MOZ_STACK_CLASS Debugger::SourceQuery : public Debugger::QueryBase
-{
-  public:
-    using SourceSet = JS::GCHashSet<JSObject*,
-                                    js::MovableCellHasher<JSObject*>,
-                                    ZoneAllocPolicy>;
-
-    SourceQuery(JSContext* cx, Debugger* dbg)
-      : QueryBase(cx, dbg),
-        sources(cx, SourceSet(cx->zone()))
-    {}
-
-    bool findSources() {
-        if (!matchAllDebuggeeGlobals())
-            return false;
-
-        Realm* singletonRealm = nullptr;
-        if (realms.count() == 1)
-            singletonRealm = realms.all().front();
-
-        // Search each realm for debuggee scripts.
-        MOZ_ASSERT(sources.empty());
-        oom = false;
-        IterateScripts(cx, singletonRealm, this, considerScript);
-        IterateLazyScripts(cx, singletonRealm, this, considerLazyScript);
-        if (oom) {
-            ReportOutOfMemory(cx);
-            return false;
-        }
-
-        // TODO: Until such time that wasm modules are real ES6 modules,
-        // unconditionally consider all wasm toplevel instance scripts.
-        for (WeakGlobalObjectSet::Range r = debugger->allDebuggees(); !r.empty(); r.popFront()) {
-            for (wasm::Instance* instance : r.front()->realm()->wasm.instances()) {
-                consider(instance->object());
-                if (oom) {
-                    ReportOutOfMemory(cx);
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    Handle<SourceSet> foundSources() const {
-        return sources;
-    }
-
-  private:
-    Rooted<SourceSet> sources;
-
-    static void considerScript(JSRuntime* rt, void* data, JSScript* script,
-                               const JS::AutoRequireNoGC& nogc) {
-        SourceQuery* self = static_cast<SourceQuery*>(data);
-        self->consider(script, nogc);
-    }
-
-    static void considerLazyScript(JSRuntime* rt, void* data, LazyScript* lazyScript,
-                                   const JS::AutoRequireNoGC& nogc) {
-        SourceQuery* self = static_cast<SourceQuery*>(data);
-        self->consider(lazyScript, nogc);
-    }
-
-    void consider(JSScript* script, const JS::AutoRequireNoGC& nogc) {
-        if (oom || script->selfHosted())
-            return;
-        Realm* realm = script->realm();
-        if (!realms.has(realm))
-            return;
-
-        if (!script->sourceObject())
-            return;
-
-        ScriptSourceObject* source =
-            &UncheckedUnwrap(script->sourceObject())->as<ScriptSourceObject>();
-        if (!sources.put(source))
-            oom = true;
-    }
-
-    void consider(LazyScript* lazyScript, const JS::AutoRequireNoGC& nogc) {
-        if (oom)
-            return;
-        Realm* realm = lazyScript->realm();
-        if (!realms.has(realm))
-            return;
-
-        // If the script is already delazified, it should already be handled.
-        if (lazyScript->maybeScript())
-            return;
-
-        ScriptSourceObject* source = &lazyScript->sourceObject();
-        if (!sources.put(source))
-            oom = true;
-    }
-
-    void consider(WasmInstanceObject* instanceObject) {
-        if (oom)
-            return;
-
-        if (!sources.put(instanceObject))
-            oom = true;
-    }
-};
-
-static inline DebuggerSourceReferent
-AsSourceReferent(JSObject* obj)
-{
-    if (obj->is<ScriptSourceObject>()) {
-        return AsVariant(&obj->as<ScriptSourceObject>());
-    }
-    return AsVariant(&obj->as<WasmInstanceObject>());
-}
-
-/* static */ bool
-Debugger::findSources(JSContext* cx, unsigned argc, Value* vp)
-{
-    THIS_DEBUGGER(cx, argc, vp, "findSources", args, dbg);
-
-    if (gc::GCRuntime::temporaryAbortIfWasmGc(cx)) {
-        JS_ReportErrorASCII(cx, "API temporarily unavailable under wasm gc");
-        return false;
-    }
-
-    SourceQuery query(cx, dbg);
-    if (!query.findSources())
-        return false;
-
-    Handle<SourceQuery::SourceSet> sources(query.foundSources());
-
-    size_t resultLength = sources.count();
-    RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, resultLength));
-    if (!result)
-        return false;
-
-    result->ensureDenseInitializedLength(cx, 0, resultLength);
-
-    size_t i = 0;
-    for (auto iter = sources.get().iter(); !iter.done(); iter.next()) {
-        Rooted<DebuggerSourceReferent> sourceReferent(cx, AsSourceReferent(iter.get()));
-        RootedObject sourceObject(cx, dbg->wrapVariantReferent(cx, sourceReferent));
-        if (!sourceObject)
-            return false;
-        result->setDenseElement(i, ObjectValue(*sourceObject));
-        i++;
-    }
-
-    args.rval().setObject(*result);
-    return true;
-}
-
-/*
  * A class for parsing 'findObjects' query arguments and searching for objects
  * that match the criteria they represent.
  */
 class MOZ_STACK_CLASS Debugger::ObjectQuery
 {
   public:
     /* Construct an ObjectQuery to use matching scripts for |dbg|. */
     ObjectQuery(JSContext* cx, Debugger* dbg) :
@@ -5336,17 +5176,16 @@ const JSFunctionSpec Debugger::methods[]
     JS_FN("addAllGlobalsAsDebuggees", Debugger::addAllGlobalsAsDebuggees, 0, 0),
     JS_FN("removeDebuggee", Debugger::removeDebuggee, 1, 0),
     JS_FN("removeAllDebuggees", Debugger::removeAllDebuggees, 0, 0),
     JS_FN("hasDebuggee", Debugger::hasDebuggee, 1, 0),
     JS_FN("getDebuggees", Debugger::getDebuggees, 0, 0),
     JS_FN("getNewestFrame", Debugger::getNewestFrame, 0, 0),
     JS_FN("clearAllBreakpoints", Debugger::clearAllBreakpoints, 0, 0),
     JS_FN("findScripts", Debugger::findScripts, 1, 0),
-    JS_FN("findSources", Debugger::findSources, 1, 0),
     JS_FN("findObjects", Debugger::findObjects, 1, 0),
     JS_FN("findAllGlobals", Debugger::findAllGlobals, 0, 0),
     JS_FN("makeGlobalObjectReference", Debugger::makeGlobalObjectReference, 1, 0),
     JS_FN("adoptDebuggeeValue", Debugger::adoptDebuggeeValue, 1, 0),
     JS_FS_END
 };
 
 const JSFunctionSpec Debugger::static_methods[] {
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -561,19 +561,17 @@ class Debugger : private mozilla::Linked
      */
 #ifdef NIGHTLY_BUILD
     uint32_t traceLoggerLastDrainedSize;
     uint32_t traceLoggerLastDrainedIteration;
 #endif
     uint32_t traceLoggerScriptedCallsLastDrainedSize;
     uint32_t traceLoggerScriptedCallsLastDrainedIteration;
 
-    class QueryBase;
     class ScriptQuery;
-    class SourceQuery;
     class ObjectQuery;
 
     MOZ_MUST_USE bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj);
     void removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
                               WeakGlobalObjectSet::Enum* debugEnum);
 
     enum class CallUncaughtExceptionHook {
         No,
@@ -715,17 +713,16 @@ class Debugger : private mozilla::Linked
     static bool addAllGlobalsAsDebuggees(JSContext* cx, unsigned argc, Value* vp);
     static bool removeDebuggee(JSContext* cx, unsigned argc, Value* vp);
     static bool removeAllDebuggees(JSContext* cx, unsigned argc, Value* vp);
     static bool hasDebuggee(JSContext* cx, unsigned argc, Value* vp);
     static bool getDebuggees(JSContext* cx, unsigned argc, Value* vp);
     static bool getNewestFrame(JSContext* cx, unsigned argc, Value* vp);
     static bool clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp);
     static bool findScripts(JSContext* cx, unsigned argc, Value* vp);
-    static bool findSources(JSContext* cx, unsigned argc, Value* vp);
     static bool findObjects(JSContext* cx, unsigned argc, Value* vp);
     static bool findAllGlobals(JSContext* cx, unsigned argc, Value* vp);
     static bool makeGlobalObjectReference(JSContext* cx, unsigned argc, Value* vp);
     static bool setupTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp);
     static bool drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp);
     static bool startTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     static bool endTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     static bool isCompilableUnit(JSContext* cx, unsigned argc, Value* vp);