Bug 1084525 - Part 5: Add onNewPromise event handler to PromisesActor r=fitzgen

This commit is contained in:
Gabriel Luong 2015-06-02 14:53:09 -07:00
Родитель d721f8d0e5
Коммит 22dde4881e
3 изменённых файлов: 121 добавлений и 12 удалений

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

@ -24,6 +24,15 @@ types.addType("ObjectActor", {
let PromisesActor = protocol.ActorClass({
typeName: "promises",
events: {
// Event emitted for new promises allocated in debuggee and bufferred by
// sending the list of promise objects in a batch.
"new-promises": {
type: "new-promises",
data: Arg(0, "array:ObjectActor"),
}
},
/**
* @param conn DebuggerServerConnection.
* @param parent TabActor|RootActor
@ -37,8 +46,10 @@ let PromisesActor = protocol.ActorClass({
this._dbg = null;
this._gripDepth = 0;
this._navigationLifetimePool = null;
this._newPromises = null;
this.objectGrip = this.objectGrip.bind(this);
this._makePromiseEventHandler = this._makePromiseEventHandler.bind(this);
this._onWindowReady = this._onWindowReady.bind(this);
},
@ -66,6 +77,8 @@ let PromisesActor = protocol.ActorClass({
this._navigationLifetimePool = this._createActorPool();
this.conn.addActorPool(this._navigationLifetimePool);
this._newPromises = [];
events.on(this.parent, "window-ready", this._onWindowReady);
this.state = "attached";
@ -81,6 +94,7 @@ let PromisesActor = protocol.ActorClass({
this.dbg.removeAllDebuggees();
this.dbg.enabled = false;
this._dbg = null;
this._newPromises = null;
if (this._navigationLifetimePool) {
this.conn.removeActorPool(this._navigationLifetimePool);
@ -110,7 +124,11 @@ let PromisesActor = protocol.ActorClass({
* An ObjectActor object that wraps the given Promise object
*/
_createObjectActorForPromise: function(promise) {
let object = new ObjectActor(promise, {
if (this._navigationLifetimePool.objectActors.has(promise)) {
return this._navigationLifetimePool.objectActors.get(promise);
}
let actor = new ObjectActor(promise, {
getGripDepth: () => this._gripDepth,
incrementGripDepth: () => this._gripDepth++,
decrementGripDepth: () => this._gripDepth--,
@ -121,8 +139,11 @@ let PromisesActor = protocol.ActorClass({
createEnvironmentActor: () => DevToolsUtils.reportException(
"PromisesActor", Error("createEnvironmentActor not yet implemented"))
});
this._navigationLifetimePool.addActor(object);
return object;
this._navigationLifetimePool.addActor(actor);
this._navigationLifetimePool.objectActors.set(promise, actor);
return actor;
},
/**
@ -134,15 +155,7 @@ let PromisesActor = protocol.ActorClass({
* The grip for the given Promise object
*/
objectGrip: function(value) {
let pool = this._navigationLifetimePool;
if (pool.objectActors.has(value)) {
return pool.objectActors.get(value).grip();
}
let actor = this._createObjectActorForPromise(value);
pool.objectActors.set(value, actor);
return actor.grip();
return this._createObjectActorForPromise(value).grip();
},
/**
@ -150,6 +163,8 @@ let PromisesActor = protocol.ActorClass({
*/
listPromises: method(function() {
let promises = this.dbg.findObjects({ class: "Promise" });
this.dbg.onNewPromise = this._makePromiseEventHandler(this._newPromises,
"new-promises");
return promises.map(p => this._createObjectActorForPromise(p));
}, {
request: {
@ -159,6 +174,31 @@ let PromisesActor = protocol.ActorClass({
}
}),
/**
* Creates an event handler for onNewPromise that will add the new
* Promise ObjectActor to the array and schedule it to be emitted as a
* batch for the provided event.
*
* @param array array
* The list of Promise ObjectActors to emit
* @param string eventName
* The event name
*/
_makePromiseEventHandler: function(array, eventName) {
return promise => {
let actor = this._createObjectActorForPromise(promise)
let needsScheduling = array.length == 0;
array.push(actor);
if (needsScheduling) {
DevToolsUtils.executeSoon(() => {
events.emit(this, eventName, array.splice(0, array.length));
});
}
}
},
_onWindowReady: expectState("attached", function({ isTopLevel }) {
if (!isTopLevel) {
return;

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

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we can get the list of all new Promise objects from the
* PromisesActor onNewPromise event handler.
*/
"use strict";
const { PromisesFront } = devtools.require("devtools/server/actors/promises");
let events = devtools.require("sdk/event/core");
add_task(function*() {
let client = yield startTestDebuggerServer("promises-actor-test");
let chromeActors = yield getChromeActors(client);
ok(Promise.toString().contains("native code"), "Expect native DOM Promise");
yield testNewPromisesEvent(client, chromeActors,
v => new Promise(resolve => resolve(v)));
let response = yield listTabs(client);
let targetTab = findTab(response.tabs, "promises-actor-test");
ok(targetTab, "Found our target tab.");
yield testNewPromisesEvent(client, targetTab, v => {
const debuggee = DebuggerServer.getTestGlobal("promises-actor-test");
return debuggee.Promise.resolve(v);
});
yield close(client);
});
function* testNewPromisesEvent(client, form, makePromise) {
let front = PromisesFront(client, form);
let resolution = "MyLittleSecret" + Math.random();
let found = false;
yield front.attach();
yield front.listPromises();
let onNewPromise = new Promise(resolve => {
events.on(front, "new-promises", promises => {
for (let p of promises) {
equal(p.type, "object", "Expect type to be Object");
equal(p.class, "Promise", "Expect class to be Promise");
if (p.promiseState.state === "fulfilled" &&
p.promiseState.value === resolution) {
found = true;
resolve();
} else {
dump("Found non-target promise\n");
}
}
});
});
let promise = makePromise(resolution);
yield onNewPromise;
ok(found, "Found our new promise");
yield front.detach();
// Appease eslint
void promise;
}

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

@ -83,6 +83,7 @@ support-files =
[test_promises_actor_attach.js]
[test_promises_actor_exist.js]
[test_promises_actor_list_promises.js]
[test_promises_actor_onnewpromise.js]
[test_protocol_abort.js]
[test_protocol_async.js]
[test_protocol_children.js]