зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1164564 - Implement WorkerActor.attachThread;r=jlong
This commit is contained in:
Родитель
5560e83bc3
Коммит
14464863a6
|
@ -45,6 +45,7 @@ support-files =
|
|||
code_ugly-8^headers^
|
||||
code_WorkerActor.attach-worker1.js
|
||||
code_WorkerActor.attach-worker2.js
|
||||
code_WorkerActor.attachThread-worker.js
|
||||
doc_auto-pretty-print-01.html
|
||||
doc_auto-pretty-print-02.html
|
||||
doc_binary_search.html
|
||||
|
@ -107,6 +108,7 @@ support-files =
|
|||
doc_with-frame.html
|
||||
doc_WorkerActor.attach-tab1.html
|
||||
doc_WorkerActor.attach-tab2.html
|
||||
doc_WorkerActor.attachThread-tab.html
|
||||
head.js
|
||||
sjs_random-javascript.sjs
|
||||
testactors.js
|
||||
|
@ -566,3 +568,5 @@ skip-if = e10s && debug
|
|||
skip-if = e10s && debug
|
||||
[browser_dbg_WorkerActor.attach.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_WorkerActor.attachThread.js]
|
||||
skip-if = e10s && debug
|
||||
|
|
|
@ -27,7 +27,6 @@ function test() {
|
|||
// registered. Instead, we have to wait for the promise returned by
|
||||
// createWorker in the tab to be resolved.
|
||||
yield createWorkerInTab(tab, WORKER1_URL);
|
||||
|
||||
let { workers } = yield listWorkers(tabClient);
|
||||
let [, workerClient1] = yield attachWorker(tabClient,
|
||||
findWorker(workers, WORKER1_URL));
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
let TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
|
||||
let WORKER_URL = "code_WorkerActor.attachThread-worker.js";
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
let client1 = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client1);
|
||||
let client2 = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client2);
|
||||
|
||||
let tab = yield addTab(TAB_URL);
|
||||
let { tabs: tabs1 } = yield listTabs(client1);
|
||||
let [, tabClient1] = yield attachTab(client1, findTab(tabs1, TAB_URL));
|
||||
let { tabs: tabs2 } = yield listTabs(client2);
|
||||
let [, tabClient2] = yield attachTab(client2, findTab(tabs2, TAB_URL));
|
||||
|
||||
yield listWorkers(tabClient1);
|
||||
yield listWorkers(tabClient2);
|
||||
yield createWorkerInTab(tab, WORKER_URL);
|
||||
let { workers: workers1 } = yield listWorkers(tabClient1);
|
||||
let [, workerClient1] = yield attachWorker(tabClient1,
|
||||
findWorker(workers1, WORKER_URL));
|
||||
let { workers: workers2 } = yield listWorkers(tabClient2);
|
||||
let [, workerClient2] = yield attachWorker(tabClient2,
|
||||
findWorker(workers2, WORKER_URL));
|
||||
|
||||
let location = { line: 5 };
|
||||
|
||||
let [, threadClient1] = yield attachThread(workerClient1);
|
||||
let sources1 = yield getSources(threadClient1);
|
||||
let sourceClient1 = threadClient1.source(findSource(sources1,
|
||||
EXAMPLE_URL + WORKER_URL));
|
||||
let [, breakpointClient1] = yield setBreakpoint(sourceClient1, location);
|
||||
yield resume(threadClient1);
|
||||
|
||||
let [, threadClient2] = yield attachThread(workerClient2);
|
||||
let sources2 = yield getSources(threadClient2);
|
||||
let sourceClient2 = threadClient2.source(findSource(sources2,
|
||||
EXAMPLE_URL + WORKER_URL));
|
||||
let [, breakpointClient2] = yield setBreakpoint(sourceClient2, location);
|
||||
yield resume(threadClient2);
|
||||
|
||||
postMessageToWorkerInTab(tab, WORKER_URL, "ping");
|
||||
yield Promise.all([
|
||||
waitForPause(threadClient1).then((packet) => {
|
||||
is(packet.type, "paused");
|
||||
let why = packet.why;
|
||||
is(why.type, "breakpoint");
|
||||
is(why.actors.length, 1);
|
||||
is(why.actors[0], breakpointClient1.actor);
|
||||
let frame = packet.frame;
|
||||
let where = frame.where;
|
||||
is(where.source.actor, sourceClient1.actor);
|
||||
is(where.line, location.line);
|
||||
let variables = frame.environment.bindings.variables;
|
||||
is(variables.a.value, 1);
|
||||
is(variables.b.value.type, "undefined");
|
||||
is(variables.c.value.type, "undefined");
|
||||
return resume(threadClient1);
|
||||
}),
|
||||
waitForPause(threadClient2).then((packet) => {
|
||||
is(packet.type, "paused");
|
||||
let why = packet.why;
|
||||
is(why.type, "breakpoint");
|
||||
is(why.actors.length, 1);
|
||||
is(why.actors[0], breakpointClient2.actor);
|
||||
let frame = packet.frame;
|
||||
let where = frame.where;
|
||||
is(where.source.actor, sourceClient2.actor);
|
||||
is(where.line, location.line);
|
||||
let variables = frame.environment.bindings.variables;
|
||||
is(variables.a.value, 1);
|
||||
is(variables.b.value.type, "undefined");
|
||||
is(variables.c.value.type, "undefined");
|
||||
return resume(threadClient2);
|
||||
}),
|
||||
]);
|
||||
|
||||
terminateWorkerInTab(tab, WORKER_URL);
|
||||
yield waitForWorkerClose(workerClient1);
|
||||
yield waitForWorkerClose(workerClient2);
|
||||
yield close(client1);
|
||||
yield close(client2);
|
||||
finish();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
}
|
||||
|
||||
self.onmessage = function (event) {
|
||||
if (event.data == "ping") {
|
||||
f()
|
||||
postMessage("pong");
|
||||
}
|
||||
};
|
||||
|
||||
postMessage("load");
|
|
@ -83,3 +83,15 @@ addMessageListener("jsonrpc", function ({ data: { method, params, id } }) {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
addMessageListener("test:postMessageToWorker", function (message) {
|
||||
dump("Posting message '" + message.data.message + "' to worker with url '" +
|
||||
message.data.url + "'.\n");
|
||||
|
||||
let worker = workers[message.data.url];
|
||||
worker.postMessage(message.data.message);
|
||||
worker.addEventListener("message", function listener() {
|
||||
worker.removeEventListener("message", listener);
|
||||
sendAsyncMessage("test:postMessageToWorker");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -512,9 +512,13 @@ function getTab(aTarget, aWindow) {
|
|||
}
|
||||
|
||||
function getSources(aClient) {
|
||||
info("Getting sources.");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
aClient.getSources(({sources}) => deferred.resolve(sources));
|
||||
aClient.getSources((packet) => {
|
||||
deferred.resolve(packet.sources);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -1129,6 +1133,15 @@ function waitForWorkerListChanged(tabClient) {
|
|||
});
|
||||
}
|
||||
|
||||
function attachThread(workerClient, options) {
|
||||
info("Attaching to thread.");
|
||||
return new Promise(function(resolve, reject) {
|
||||
workerClient.attachThread(options, function (response, threadClient) {
|
||||
resolve([response, threadClient]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerClose(workerClient) {
|
||||
info("Waiting for worker to close.");
|
||||
return new Promise(function (resolve) {
|
||||
|
@ -1156,3 +1169,52 @@ function waitForWorkerThaw(workerClient) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
function resume(threadClient) {
|
||||
info("Resuming thread.");
|
||||
return rdpInvoke(threadClient, threadClient.resume);
|
||||
}
|
||||
|
||||
function findSource(sources, url) {
|
||||
info("Finding source with url '" + url + "'.\n");
|
||||
for (let source of sources) {
|
||||
if (source.url === url) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function setBreakpoint(sourceClient, location) {
|
||||
info("Setting breakpoint.\n");
|
||||
return new Promise(function (resolve) {
|
||||
sourceClient.setBreakpoint(location, function (response, breakpointClient) {
|
||||
resolve([response, breakpointClient]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForEvent(client, type, predicate) {
|
||||
return new Promise(function (resolve) {
|
||||
function listener(type, packet) {
|
||||
if (!predicate(packet)) {
|
||||
return;
|
||||
}
|
||||
client.removeListener(listener);
|
||||
resolve(packet);
|
||||
}
|
||||
|
||||
if (predicate) {
|
||||
client.addListener(type, listener);
|
||||
} else {
|
||||
client.addOneTimeListener(type, function (type, packet) {
|
||||
resolve(packet);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function waitForPause(threadClient) {
|
||||
info("Waiting for pause.\n");
|
||||
return waitForEvent(threadClient, "paused");
|
||||
}
|
||||
|
|
|
@ -1360,7 +1360,7 @@ TabClient.prototype = {
|
|||
eventSource(TabClient.prototype);
|
||||
|
||||
function WorkerClient(aClient, aForm) {
|
||||
this._client = aClient;
|
||||
this.client = aClient;
|
||||
this._actor = aForm.from;
|
||||
this._isClosed = false;
|
||||
this._isFrozen = aForm.isFrozen;
|
||||
|
@ -1376,11 +1376,11 @@ function WorkerClient(aClient, aForm) {
|
|||
|
||||
WorkerClient.prototype = {
|
||||
get _transport() {
|
||||
return this._client._transport;
|
||||
return this.client._transport;
|
||||
},
|
||||
|
||||
get request() {
|
||||
return this._client.request;
|
||||
return this.client.request;
|
||||
},
|
||||
|
||||
get actor() {
|
||||
|
@ -1397,19 +1397,41 @@ WorkerClient.prototype = {
|
|||
|
||||
detach: DebuggerClient.requester({ type: "detach" }, {
|
||||
after: function (aResponse) {
|
||||
this._client.unregisterClient(this);
|
||||
this.client.unregisterClient(this);
|
||||
return aResponse;
|
||||
},
|
||||
|
||||
telemetry: "WORKERDETACH"
|
||||
}),
|
||||
|
||||
attachThread: function(aOptions = {}, aOnResponse = noop) {
|
||||
if (this.thread) {
|
||||
DevToolsUtils.executeSoon(() => aOnResponse({
|
||||
type: "connected",
|
||||
threadActor: this.thread._actor,
|
||||
}, this.thread));
|
||||
return;
|
||||
}
|
||||
|
||||
this.request({
|
||||
to: this._actor,
|
||||
type: "connect",
|
||||
options: aOptions,
|
||||
}, (aResponse) => {
|
||||
if (!aResponse.error) {
|
||||
this.thread = new ThreadClient(this, aResponse.threadActor);
|
||||
this.client.registerClient(this.thread);
|
||||
}
|
||||
aOnResponse(aResponse, this.thread);
|
||||
});
|
||||
},
|
||||
|
||||
_onClose: function () {
|
||||
this.removeListener("close", this._onClose);
|
||||
this.removeListener("freeze", this._onFreeze);
|
||||
this.removeListener("thaw", this._onThaw);
|
||||
|
||||
this._client.unregisterClient(this);
|
||||
this.client.unregisterClient(this);
|
||||
this._closed = true;
|
||||
},
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
|
|||
const { dbg_assert, dumpn, update, fetch } = DevToolsUtils;
|
||||
const { dirname, joinURI } = require("devtools/toolkit/path");
|
||||
const promise = require("promise");
|
||||
const PromiseDebugging = require("PromiseDebugging");
|
||||
const xpcInspector = require("xpcInspector");
|
||||
const ScriptStore = require("./utils/ScriptStore");
|
||||
const {DevToolsWorker} = require("devtools/toolkit/shared/worker.js");
|
||||
|
@ -1494,7 +1495,7 @@ ThreadActor.prototype = {
|
|||
// Clear DOM event breakpoints.
|
||||
// XPCShell tests don't use actual DOM windows for globals and cause
|
||||
// removeListenerForAllEvents to throw.
|
||||
if (this.global && !this.global.toString().includes("Sandbox")) {
|
||||
if (!isWorker && this.global && !this.global.toString().includes("Sandbox")) {
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
els.removeListenerForAllEvents(this.global, this._allEventsListener, true);
|
||||
|
@ -1933,7 +1934,7 @@ ThreadActor.prototype = {
|
|||
}
|
||||
|
||||
if (promises.length > 0) {
|
||||
this.synchronize(Promise.all(promises));
|
||||
this.synchronize(promise.all(promises));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2870,10 +2871,10 @@ SourceActor.prototype = {
|
|||
actor,
|
||||
GeneratedLocation.fromOriginalLocation(originalLocation)
|
||||
)) {
|
||||
return Promise.resolve(null);
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
return Promise.resolve(originalLocation);
|
||||
return promise.resolve(originalLocation);
|
||||
} else {
|
||||
return this.sources.getAllGeneratedLocations(originalLocation)
|
||||
.then((generatedLocations) => {
|
||||
|
|
|
@ -10,7 +10,7 @@ const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
|
|||
const { dbg_assert, fetch } = DevToolsUtils;
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const { OriginalLocation, GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
|
||||
const { resolve } = Promise;
|
||||
const { resolve } = require("promise");
|
||||
|
||||
loader.lazyRequireGetter(this, "SourceActor", "devtools/server/actors/script", true);
|
||||
loader.lazyRequireGetter(this, "isEvalSource", "devtools/server/actors/script", true);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
let { Ci, Cu } = require("chrome");
|
||||
let { DebuggerServer } = require("devtools/server/main");
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
@ -28,6 +29,8 @@ function matchWorkerDebugger(dbg, options) {
|
|||
function WorkerActor(dbg) {
|
||||
this._dbg = dbg;
|
||||
this._isAttached = false;
|
||||
this._threadActor = null;
|
||||
this._transport = null;
|
||||
}
|
||||
|
||||
WorkerActor.prototype = {
|
||||
|
@ -66,6 +69,33 @@ WorkerActor.prototype = {
|
|||
return { type: "detached" };
|
||||
},
|
||||
|
||||
onConnect: function (request) {
|
||||
if (!this._isAttached) {
|
||||
return { error: "wrongState" };
|
||||
}
|
||||
|
||||
if (this._threadActor !== null) {
|
||||
return {
|
||||
type: "connected",
|
||||
threadActor: this._threadActor
|
||||
};
|
||||
}
|
||||
|
||||
return DebuggerServer.connectToWorker(
|
||||
this.conn, this._dbg, this.actorID, request.options
|
||||
).then(({ threadActor, transport }) => {
|
||||
this._threadActor = threadActor;
|
||||
this._transport = transport;
|
||||
|
||||
return {
|
||||
type: "connected",
|
||||
threadActor: this._threadActor
|
||||
};
|
||||
}, (error) => {
|
||||
return { error: error.toString() };
|
||||
});
|
||||
},
|
||||
|
||||
onClose: function () {
|
||||
if (this._isAttached) {
|
||||
this._detach();
|
||||
|
@ -74,6 +104,10 @@ WorkerActor.prototype = {
|
|||
this.conn.sendActorEvent(this.actorID, "close");
|
||||
},
|
||||
|
||||
onError: function (filename, lineno, message) {
|
||||
reportError("ERROR:" + filename + ":" + lineno + ":" + message + "\n");
|
||||
},
|
||||
|
||||
onFreeze: function () {
|
||||
this.conn.sendActorEvent(this.actorID, "freeze");
|
||||
},
|
||||
|
@ -83,6 +117,12 @@ WorkerActor.prototype = {
|
|||
},
|
||||
|
||||
_detach: function () {
|
||||
if (this._threadActor !== null) {
|
||||
this._transport.close();
|
||||
this._transport = null;
|
||||
this._threadActor = null;
|
||||
}
|
||||
|
||||
this._dbg.removeListener(this);
|
||||
this._isAttached = false;
|
||||
}
|
||||
|
@ -90,7 +130,8 @@ WorkerActor.prototype = {
|
|||
|
||||
WorkerActor.prototype.requestTypes = {
|
||||
"attach": WorkerActor.prototype.onAttach,
|
||||
"detach": WorkerActor.prototype.onDetach
|
||||
"detach": WorkerActor.prototype.onDetach,
|
||||
"connect": WorkerActor.prototype.onConnect
|
||||
};
|
||||
|
||||
exports.WorkerActor = WorkerActor;
|
||||
|
|
|
@ -14,7 +14,7 @@ let { Ci, Cc, CC, Cu, Cr } = require("chrome");
|
|||
let Services = require("Services");
|
||||
let { ActorPool, OriginalLocation, RegisteredActorFactory,
|
||||
ObservedActorFactory } = require("devtools/server/actors/common");
|
||||
let { LocalDebuggerTransport, ChildDebuggerTransport } =
|
||||
let { LocalDebuggerTransport, ChildDebuggerTransport, WorkerDebuggerTransport } =
|
||||
require("devtools/toolkit/transport/transport");
|
||||
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
|
||||
let { dumpn, dumpv, dbg_assert } = DevToolsUtils;
|
||||
|
@ -685,10 +685,13 @@ var DebuggerServer = {
|
|||
* "debug:<prefix>:packet", and all its actors will have names
|
||||
* beginning with "<prefix>/".
|
||||
*/
|
||||
connectToParent: function(aPrefix, aMessageManager) {
|
||||
connectToParent: function(aPrefix, aScopeOrManager) {
|
||||
this._checkInit();
|
||||
|
||||
let transport = new ChildDebuggerTransport(aMessageManager, aPrefix);
|
||||
let transport = isWorker ?
|
||||
new WorkerDebuggerTransport(aScopeOrManager, aPrefix) :
|
||||
new ChildDebuggerTransport(aScopeOrManager, aPrefix);
|
||||
|
||||
return this._onConnection(transport, aPrefix, true);
|
||||
},
|
||||
|
||||
|
@ -755,6 +758,83 @@ var DebuggerServer = {
|
|||
return deferred.promise;
|
||||
},
|
||||
|
||||
connectToWorker: function (aConnection, aDbg, aId, aOptions) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Step 1: Initialize the worker debugger.
|
||||
aDbg.initialize("resource://gre/modules/devtools/server/worker.js");
|
||||
|
||||
// Step 2: Send a connect request to the worker debugger.
|
||||
aDbg.postMessage(JSON.stringify({
|
||||
type: "connect",
|
||||
id: aId,
|
||||
options: aOptions
|
||||
}));
|
||||
|
||||
// Steps 3-5 are performed on the worker thread (see worker.js).
|
||||
|
||||
// Step 6: Wait for a response from the worker debugger.
|
||||
let listener = {
|
||||
onClose: () => {
|
||||
aDbg.removeListener(listener);
|
||||
|
||||
reject("closed");
|
||||
},
|
||||
|
||||
onMessage: (message) => {
|
||||
let packet = JSON.parse(message);
|
||||
if (packet.type !== "message" || packet.id !== aId) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = packet.message;
|
||||
if (message.error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
if (message.type !== "paused") {
|
||||
return;
|
||||
}
|
||||
|
||||
aDbg.removeListener(listener);
|
||||
|
||||
// Step 7: Create a transport for the connection to the worker.
|
||||
let transport = new WorkerDebuggerTransport(aDbg, aId);
|
||||
transport.ready();
|
||||
transport.hooks = {
|
||||
onClosed: () => {
|
||||
if (!aDbg.isClosed) {
|
||||
aDbg.postMessage(JSON.stringify({
|
||||
type: "disconnect",
|
||||
id: aId
|
||||
}));
|
||||
}
|
||||
|
||||
aConnection.cancelForwarding(aId);
|
||||
},
|
||||
|
||||
onPacket: (packet) => {
|
||||
// Ensure that any packets received from the server on the worker
|
||||
// thread are forwarded to the client on the main thread, as if
|
||||
// they had been sent by the server on the main thread.
|
||||
aConnection.send(packet);
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure that any packets received from the client on the main thread
|
||||
// to actors on the worker thread are forwarded to the server on the
|
||||
// worker thread.
|
||||
aConnection.setForwarding(aId, transport);
|
||||
|
||||
resolve({
|
||||
threadActor: message.from,
|
||||
transport: transport
|
||||
});
|
||||
}
|
||||
};
|
||||
aDbg.addListener(listener);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the caller is running in a content child process.
|
||||
*
|
||||
|
|
|
@ -51,6 +51,7 @@ EXTRA_JS_MODULES.devtools.server += [
|
|||
'content-globals.js',
|
||||
'main.js',
|
||||
'protocol.js',
|
||||
'worker.js'
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.devtools.server.actors += [
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
"use strict"
|
||||
|
||||
loadSubScript("resource://gre/modules/devtools/worker-loader.js");
|
||||
|
||||
let { ActorPool } = worker.require("devtools/server/actors/common");
|
||||
let { ThreadActor } = worker.require("devtools/server/actors/script");
|
||||
let { TabSources } = worker.require("devtools/server/actors/utils/TabSources");
|
||||
let makeDebugger = worker.require("devtools/server/actors/utils/make-debugger");
|
||||
let { DebuggerServer } = worker.require("devtools/server/main");
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.createRootActor = function () {
|
||||
throw new Error("Should never get here!");
|
||||
};
|
||||
|
||||
let connections = Object.create(null);
|
||||
|
||||
this.addEventListener("message", function (event) {
|
||||
let packet = JSON.parse(event.data);
|
||||
switch (packet.type) {
|
||||
case "connect":
|
||||
// Step 3: Create a connection to the parent.
|
||||
let connection = DebuggerServer.connectToParent(packet.id, this);
|
||||
connections[packet.id] = connection;
|
||||
|
||||
// Step 4: Create a thread actor for the connection to the parent.
|
||||
let pool = new ActorPool(connection);
|
||||
connection.addActorPool(pool);
|
||||
|
||||
let sources = null;
|
||||
|
||||
let actor = new ThreadActor({
|
||||
makeDebugger: makeDebugger.bind(null, {
|
||||
findDebuggees: () => {
|
||||
return [this.global];
|
||||
},
|
||||
|
||||
shouldAddNewGlobalAsDebuggee: () => {
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
|
||||
get sources() {
|
||||
if (sources === null) {
|
||||
sources = new TabSources(actor);
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
}, global);
|
||||
|
||||
pool.addActor(actor);
|
||||
|
||||
// Step 5: Attach to the thread actor.
|
||||
//
|
||||
// This will cause a packet to be sent over the connection to the parent.
|
||||
// Because this connection uses WorkerDebuggerTransport internally, this
|
||||
// packet will be sent using WorkerDebuggerGlobalScope.postMessage, causing
|
||||
// an onMessage event to be fired on the WorkerDebugger in the main thread.
|
||||
actor.onAttach({});
|
||||
break;
|
||||
|
||||
case "disconnect":
|
||||
connections[packet.id].close();
|
||||
break;
|
||||
};
|
||||
});
|
|
@ -435,6 +435,8 @@ let {
|
|||
} else { // Worker thread
|
||||
let requestors = [];
|
||||
|
||||
let scope = this;
|
||||
|
||||
let xpcInspector = {
|
||||
get lastNestRequestor() {
|
||||
return requestors.length === 0 ? null : requestors[0];
|
||||
|
@ -442,13 +444,13 @@ let {
|
|||
|
||||
enterNestedEventLoop: function (requestor) {
|
||||
requestors.push(requestor);
|
||||
this.enterEventLoop();
|
||||
scope.enterEventLoop();
|
||||
return requestors.length;
|
||||
},
|
||||
|
||||
exitNestedEventLoop: function () {
|
||||
requestors.pop();
|
||||
this.leaveEventLoop();
|
||||
scope.leaveEventLoop();
|
||||
return requestors.length;
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче