Bug 1506549 - Introduce API to listen for new child fronts of a given type. r=yulia

MozReview-Commit-ID: EKWTGhGo0VM

Depends on D11624

Differential Revision: https://phabricator.services.mozilla.com/D11625

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alexandre Poirot 2018-11-15 10:23:00 +00:00
Родитель 5eed35c08e
Коммит 78e2ca28f0
3 изменённых файлов: 153 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,131 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test Front.onFront method.
*/
const protocol = require("devtools/shared/protocol");
const {RetVal} = protocol;
const childSpec = protocol.generateActorSpec({
typeName: "childActor",
});
const ChildActor = protocol.ActorClassWithSpec(childSpec, {
initialize(conn, id) {
protocol.Actor.prototype.initialize.call(this, conn);
this.childID = id;
},
form: function(detail) {
if (detail === "actorid") {
return this.actorID;
}
return {
actor: this.actorID,
childID: this.childID,
};
},
});
const rootSpec = protocol.generateActorSpec({
typeName: "root",
methods: {
createChild: {
request: {},
response: { actor: RetVal("childActor") },
},
},
});
const RootActor = protocol.ActorClassWithSpec(rootSpec, {
typeName: "root",
initialize: function(conn) {
protocol.Actor.prototype.initialize.call(this, conn);
this.actorID = "root";
// Root actor owns itself.
this.manage(this);
this.sequence = 0;
},
sayHello() {
return {
from: "root",
applicationType: "xpcshell-tests",
traits: [],
};
},
createChild() {
return new ChildActor(this.conn, this.sequence++);
},
});
const ChildFront = protocol.FrontClassWithSpec(childSpec, {
form(form, detail) {
if (detail === "actorid") {
return;
}
this.childID = form.childID;
},
});
const RootFront = protocol.FrontClassWithSpec(rootSpec, {
initialize(client) {
this.actorID = "root";
protocol.Front.prototype.initialize.call(this, client);
// Root owns itself.
this.manage(this);
},
});
add_task(async function run_test() {
DebuggerServer.createRootActor = RootActor;
DebuggerServer.init();
const trace = connectPipeTracing();
const client = new DebuggerClient(trace);
await client.connect();
const rootFront = new RootFront(client);
const fronts = [];
rootFront.onFront("childActor", front => {
fronts.push(front);
});
const firstChild = await rootFront.createChild();
ok(firstChild instanceof ChildFront, "createChild returns a ChildFront instance");
equal(firstChild.childID, 0, "First child has ID=0");
equal(fronts.length, 1,
"onFront fires the callback, even if the front is created in the future");
equal(fronts[0], firstChild,
"onFront fires the callback with the right front instance");
const onFrontAfter = await new Promise(resolve => {
rootFront.onFront("childActor", resolve);
});
equal(onFrontAfter, firstChild,
"onFront fires the callback, even if the front is already created, " +
" with the same front instance");
equal(fronts.length, 1,
"There is still only one front reported from the first listener");
const secondChild = await rootFront.createChild();
equal(fronts.length, 2, "After a second call to createChild, two fronts are reported");
equal(fronts[1], secondChild, "And the new front is the right instance");
trace.close();
await client.close();
});

Просмотреть файл

@ -106,6 +106,7 @@ skip-if = coverage # bug 1336670
[test_protocol_children.js]
[test_protocol_formtype.js]
[test_protocol_longstring.js]
[test_protocol_onFront.js]
[test_protocol_simple.js]
[test_protocol_stack.js]
[test_protocol_unregister.js]

Просмотреть файл

@ -1285,6 +1285,10 @@ var Front = function(conn = null, form = null, detail = null, context = null) {
Pool.call(this, conn);
this._requests = [];
// Front listener functions registered via `onFront` get notified
// of new fronts via this dedicated EventEmitter object.
this._frontListeners = new EventEmitter();
// protocol.js no longer uses this data in the constructor, only external
// uses do. External usage of manually-constructed fronts will be
// drastically reduced if we convert the root and target actors to
@ -1314,6 +1318,7 @@ Front.prototype = extend(Pool.prototype, {
}
Pool.prototype.destroy.call(this);
this.actorID = null;
this._frontListeners = null;
},
manage: function(front) {
@ -1322,6 +1327,22 @@ Front.prototype = extend(Pool.prototype, {
"Ensure server supports " + front.typeName + ".");
}
Pool.prototype.manage.call(this, front);
// Call listeners registered via `onFront` method
this._frontListeners.emit(front.typeName, front);
},
// Run callback on every front of this type that currently exists, and on every
// instantiation of front type in the future.
onFront(typeName, callback) {
// First fire the callback on already instantiated fronts
for (const front of this.poolChildren()) {
if (front.typeName == typeName) {
callback(front);
}
}
// Then register the callback for fronts instantiated in the future
this._frontListeners.on(typeName, callback);
},
toString: function() {