mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
298 lines
7.9 KiB
JavaScript
298 lines
7.9 KiB
JavaScript
var Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
// Always log packets when running tests.
|
|
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
|
SimpleTest.registerCleanupFunction(function() {
|
|
Services.prefs.clearUserPref("devtools.debugger.log");
|
|
});
|
|
|
|
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
|
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
|
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
|
|
|
const {_documentWalker} = devtools.require("devtools/server/actors/inspector");
|
|
|
|
if (!DebuggerServer.initialized) {
|
|
DebuggerServer.init(() => true);
|
|
DebuggerServer.addBrowserActors();
|
|
SimpleTest.registerCleanupFunction(function() {
|
|
DebuggerServer.destroy();
|
|
});
|
|
}
|
|
|
|
var gAttachCleanups = [];
|
|
|
|
SimpleTest.registerCleanupFunction(function() {
|
|
for (let cleanup of gAttachCleanups) {
|
|
cleanup();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Open a tab, load the url, wait for it to signal its readiness,
|
|
* find the tab with the debugger server, and call the callback.
|
|
*
|
|
* Returns a function which can be called to close the opened ta
|
|
* and disconnect its debugger client.
|
|
*/
|
|
function attachURL(url, callback) {
|
|
var win = window.open(url, "_blank");
|
|
var client = null;
|
|
|
|
let cleanup = () => {
|
|
if (client) {
|
|
client.close();
|
|
client = null;
|
|
}
|
|
if (win) {
|
|
win.close();
|
|
win = null;
|
|
}
|
|
};
|
|
gAttachCleanups.push(cleanup);
|
|
|
|
window.addEventListener("message", function loadListener(event) {
|
|
if (event.data === "ready") {
|
|
client = new DebuggerClient(DebuggerServer.connectPipe());
|
|
client.connect((applicationType, traits) => {
|
|
client.listTabs(response => {
|
|
for (let tab of response.tabs) {
|
|
if (tab.url === url) {
|
|
window.removeEventListener("message", loadListener, false);
|
|
try {
|
|
callback(null, client, tab, win.document);
|
|
} catch(ex) {
|
|
Cu.reportError(ex);
|
|
dump(ex);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}, false);
|
|
|
|
return cleanup;
|
|
}
|
|
|
|
function promiseOnce(target, event) {
|
|
let deferred = promise.defer();
|
|
target.on(event, (...args) => {
|
|
if (args.length === 1) {
|
|
deferred.resolve(args[0]);
|
|
} else {
|
|
deferred.resolve(args);
|
|
}
|
|
});
|
|
return deferred.promise;
|
|
}
|
|
|
|
function sortOwnershipChildren(children) {
|
|
return children.sort((a, b) => a.name.localeCompare(b.name));
|
|
}
|
|
|
|
function serverOwnershipSubtree(walker, node) {
|
|
let actor = walker._refMap.get(node);
|
|
if (!actor) {
|
|
return undefined;
|
|
}
|
|
|
|
let children = [];
|
|
let docwalker = _documentWalker(node, window);
|
|
let child = docwalker.firstChild();
|
|
while (child) {
|
|
let item = serverOwnershipSubtree(walker, child);
|
|
if (item) {
|
|
children.push(item);
|
|
}
|
|
child = docwalker.nextSibling();
|
|
}
|
|
return {
|
|
name: actor.actorID,
|
|
children: sortOwnershipChildren(children)
|
|
}
|
|
}
|
|
|
|
function serverOwnershipTree(walker) {
|
|
let serverConnection = walker.conn._transport._serverConnection;
|
|
let serverWalker = serverConnection.getActor(walker.actorID);
|
|
|
|
return {
|
|
root: serverOwnershipSubtree(serverWalker, serverWalker.rootDoc ),
|
|
orphaned: [serverOwnershipSubtree(serverWalker, o.rawNode) for (o of serverWalker._orphaned)],
|
|
retained: [serverOwnershipSubtree(serverWalker, o.rawNode) for (o of serverWalker._retainedOrphans)]
|
|
};
|
|
}
|
|
|
|
function clientOwnershipSubtree(node) {
|
|
return {
|
|
name: node.actorID,
|
|
children: sortOwnershipChildren([clientOwnershipSubtree(child) for (child of node.treeChildren())])
|
|
}
|
|
}
|
|
|
|
function clientOwnershipTree(walker) {
|
|
return {
|
|
root: clientOwnershipSubtree(walker.rootNode),
|
|
orphaned: [clientOwnershipSubtree(o) for (o of walker._orphaned)],
|
|
retained: [clientOwnershipSubtree(o) for (o of walker._retainedOrphans)]
|
|
}
|
|
}
|
|
|
|
function ownershipTreeSize(tree) {
|
|
let size = 1;
|
|
for (let child of tree.children) {
|
|
size += ownershipTreeSize(child);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
function assertOwnershipTrees(walker) {
|
|
let serverTree = serverOwnershipTree(walker);
|
|
let clientTree = clientOwnershipTree(walker);
|
|
is(JSON.stringify(clientTree, null, ' '), JSON.stringify(serverTree, null, ' '), "Server and client ownership trees should match.");
|
|
|
|
return ownershipTreeSize(clientTree.root);
|
|
}
|
|
|
|
// Verify that an actorID is inaccessible both from the client library and the server.
|
|
function checkMissing(client, actorID) {
|
|
let deferred = promise.defer();
|
|
let front = client.getActor(actorID);
|
|
ok(!front, "Front shouldn't be accessible from the client for actorID: " + actorID);
|
|
|
|
let deferred = promise.defer();
|
|
client.request({
|
|
to: actorID,
|
|
type: "request",
|
|
}, response => {
|
|
is(response.error, "noSuchActor", "node list actor should no longer be contactable.");
|
|
deferred.resolve(undefined);
|
|
});
|
|
return deferred.promise;
|
|
}
|
|
|
|
// Verify that an actorID is accessible both from the client library and the server.
|
|
function checkAvailable(client, actorID) {
|
|
let deferred = promise.defer();
|
|
let front = client.getActor(actorID);
|
|
ok(front, "Front should be accessible from the client for actorID: " + actorID);
|
|
|
|
let deferred = promise.defer();
|
|
client.request({
|
|
to: actorID,
|
|
type: "garbageAvailableTest",
|
|
}, response => {
|
|
is(response.error, "unrecognizedPacketType", "node list actor should be contactable.");
|
|
deferred.resolve(undefined);
|
|
});
|
|
return deferred.promise;
|
|
}
|
|
|
|
function promiseDone(promise) {
|
|
promise.then(null, err => {
|
|
ok(false, "Promise failed: " + err);
|
|
if (err.stack) {
|
|
dump(err.stack);
|
|
}
|
|
SimpleTest.finish();
|
|
});
|
|
}
|
|
|
|
// Mutation list testing
|
|
|
|
function isSrcChange(change) {
|
|
return (change.type === "attributes" && change.attributeName === "src");
|
|
}
|
|
|
|
function assertAndStrip(mutations, message, test) {
|
|
let size = mutations.length;
|
|
mutations = mutations.filter(test);
|
|
ok((mutations.size != size), message);
|
|
return mutations;
|
|
}
|
|
|
|
function isSrcChange(change) {
|
|
return change.type === "attributes" && change.attributeName === "src";
|
|
}
|
|
|
|
function isUnload(change) {
|
|
return change.type === "documentUnload";
|
|
}
|
|
|
|
function isFrameLoad(change) {
|
|
return change.type === "frameLoad";
|
|
}
|
|
|
|
function isUnretained(change) {
|
|
return change.type === "unretained";
|
|
}
|
|
|
|
function isChildList(change) {
|
|
return change.type === "childList";
|
|
}
|
|
|
|
function isNewRoot(change) {
|
|
return change.type === "newRoot";
|
|
}
|
|
|
|
// Make sure an iframe's src attribute changed and then
|
|
// strip that mutation out of the list.
|
|
function assertSrcChange(mutations) {
|
|
return assertAndStrip(mutations, "Should have had an iframe source change.", isSrcChange);
|
|
}
|
|
|
|
// Make sure there's an unload in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertUnload(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a document unload change.", isUnload);
|
|
}
|
|
|
|
// Make sure there's a frame load in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertFrameLoad(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a frame load change.", isFrameLoad);
|
|
}
|
|
|
|
// Make sure there's a childList change in the mutation list and strip
|
|
// that mutation out of the list
|
|
function assertChildList(mutations) {
|
|
return assertAndStrip(mutations, "Should have had a frame load change.", isChildList);
|
|
}
|
|
|
|
// Load mutations aren't predictable, so keep accumulating mutations until
|
|
// the one we're looking for shows up.
|
|
function waitForMutation(walker, test, mutations=[]) {
|
|
let deferred = promise.defer();
|
|
for (let change of mutations) {
|
|
if (test(change)) {
|
|
deferred.resolve(mutations);
|
|
}
|
|
}
|
|
|
|
walker.once("mutations", newMutations => {
|
|
waitForMutation(walker, test, mutations.concat(newMutations)).then(finalMutations => {
|
|
deferred.resolve(finalMutations);
|
|
})
|
|
});
|
|
|
|
return deferred.promise;
|
|
}
|
|
|
|
|
|
var _tests = [];
|
|
function addTest(test) {
|
|
_tests.push(test);
|
|
}
|
|
|
|
function runNextTest() {
|
|
if (_tests.length == 0) {
|
|
SimpleTest.finish()
|
|
return;
|
|
}
|
|
_tests.shift()();
|
|
}
|