This patch was autogenerated by my decomponents.py
It covers almost every file with the extension js, jsm, html, py,
xhtml, or xul.
It removes blank lines after removed lines, when the removed lines are
preceded by either blank lines or the start of a new block. The "start
of a new block" is defined fairly hackily: either the line starts with
//, ends with */, ends with {, <![CDATA[, """ or '''. The first two
cover comments, the third one covers JS, the fourth covers JS embedded
in XUL, and the final two cover JS embedded in Python. This also
applies if the removed line was the first line of the file.
It covers the pattern matching cases like "var {classes: Cc,
interfaces: Ci, utils: Cu, results: Cr} = Components;". It'll remove
the entire thing if they are all either Ci, Cr, Cc or Cu, or it will
remove the appropriate ones and leave the residue behind. If there's
only one behind, then it will turn it into a normal, non-pattern
matching variable definition. (For instance, "const { classes: Cc,
Constructor: CC, interfaces: Ci, utils: Cu } = Components" becomes
"const CC = Components.Constructor".)
MozReview-Commit-ID: DeSHcClQ7cG
184 lines
6.6 KiB
JavaScript
184 lines
6.6 KiB
JavaScript
/* globals Components: true, Promise: true, gBrowser: true, Test: true,
|
|
info: true, is: true, window: true, waitForExplicitFinish: true,
|
|
finish: true, ok: true*/
|
|
|
|
"use strict";
|
|
|
|
const { addObserver, removeObserver } = Cc["@mozilla.org/observer-service;1"].
|
|
getService(Ci.nsIObserverService);
|
|
const { openWindow } = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
|
getService(Ci.nsIWindowWatcher);
|
|
|
|
const Test = routine => () => {
|
|
waitForExplicitFinish();
|
|
routine()
|
|
.then(finish, error => {
|
|
ok(false, error);
|
|
finish();
|
|
});
|
|
};
|
|
|
|
// Returns promise for the observer notification subject for
|
|
// the given topic. If `receive("foo")` is called `n` times
|
|
// nth promise is resolved on an `nth` "foo" notification.
|
|
const receive = (topic, p, syncCallback) => {
|
|
return new Promise((resolve, reject) => {
|
|
const { queue } = receive;
|
|
const timeout = () => {
|
|
queue.splice(queue.indexOf(resolve) - 1, 2);
|
|
reject(new Error("Timeout"));
|
|
};
|
|
|
|
const observer = {
|
|
observe: subject => {
|
|
// Browser loads bunch of other documents that we don't care
|
|
// about so we let allow filtering notifications via `p` function.
|
|
if (p && !p(subject)) return;
|
|
// If observer is a first one with a given `topic`
|
|
// in a queue resolve promise and take it off the queue
|
|
// otherwise keep waiting.
|
|
const index = queue.indexOf(topic);
|
|
if (queue.indexOf(resolve) === index + 1) {
|
|
removeObserver(observer, topic);
|
|
clearTimeout(id, reject);
|
|
queue.splice(index, 2);
|
|
// Some tests need to be executed synchronously when the event is fired.
|
|
if (syncCallback) {
|
|
syncCallback(subject);
|
|
}
|
|
resolve(subject);
|
|
}
|
|
}
|
|
};
|
|
const id = setTimeout(timeout, 90000);
|
|
addObserver(observer, topic, false);
|
|
queue.push(topic, resolve);
|
|
});
|
|
};
|
|
receive.queue = [];
|
|
|
|
const openTab = uri => gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, uri);
|
|
|
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
const isData = document => document.URL.startsWith("data:");
|
|
|
|
const uri1 = "data:text/html;charset=utf-8,<h1>1</h1>";
|
|
// For whatever reason going back on load event doesn't work so timeout it is :(
|
|
const uri2 = "data:text/html;charset=utf-8,<h1>2</h1><script>setTimeout(SpecialPowers.wrap(window).back,100)</script>";
|
|
const uri3 = "data:text/html;charset=utf-8,<h1>3</h1>";
|
|
|
|
const uri4 = "chrome://browser/content/license.html";
|
|
|
|
const test = Test(async function() {
|
|
let documentInteractive = receive("content-document-interactive", isData, d => {
|
|
// This test is executed synchronously when the event is received.
|
|
is(d.readyState, "interactive", "document is interactive");
|
|
is(d.URL, uri1, "document.URL matches tab url");
|
|
});
|
|
let documentLoaded = receive("content-document-loaded", isData);
|
|
let pageShown = receive("content-page-shown", isData);
|
|
|
|
info("open: uri#1");
|
|
const tab1 = openTab(uri1);
|
|
const browser1 = gBrowser.getBrowserForTab(tab1);
|
|
|
|
let interactiveDocument1 = await documentInteractive;
|
|
|
|
let loadedDocument1 = await documentLoaded;
|
|
is(loadedDocument1.readyState, "complete", "document is loaded");
|
|
is(interactiveDocument1, loadedDocument1, "interactive document is loaded");
|
|
|
|
let shownPage = await pageShown;
|
|
is(interactiveDocument1, shownPage, "loaded document is shown");
|
|
|
|
// Wait until history entry is created before loading new uri.
|
|
await receive("sessionstore-state-write-complete");
|
|
|
|
info("load uri#2");
|
|
|
|
documentInteractive = receive("content-document-interactive", isData, d => {
|
|
// This test is executed synchronously when the event is received.
|
|
is(d.readyState, "interactive", "document is interactive");
|
|
is(d.URL, uri2, "document.URL matches URL loaded");
|
|
});
|
|
documentLoaded = receive("content-document-loaded", isData);
|
|
pageShown = receive("content-page-shown", isData);
|
|
let pageHidden = receive("content-page-hidden", isData);
|
|
|
|
browser1.loadURI(uri2);
|
|
|
|
let hiddenPage = await pageHidden;
|
|
is(interactiveDocument1, hiddenPage, "loaded document is hidden");
|
|
|
|
let interactiveDocument2 = await documentInteractive;
|
|
|
|
let loadedDocument2 = await documentLoaded;
|
|
is(loadedDocument2.readyState, "complete", "document is loaded");
|
|
is(interactiveDocument2, loadedDocument2, "interactive document is loaded");
|
|
|
|
shownPage = await pageShown;
|
|
is(interactiveDocument2, shownPage, "loaded document is shown");
|
|
|
|
info("go back to uri#1");
|
|
|
|
|
|
documentInteractive = receive("content-document-interactive", isData, d => {
|
|
// This test is executed synchronously when the event is received.
|
|
is(d.readyState, "interactive", "document is interactive");
|
|
is(d.URL, uri3, "document.URL matches URL loaded");
|
|
});
|
|
documentLoaded = receive("content-document-loaded", isData);
|
|
pageShown = receive("content-page-shown", isData);
|
|
pageHidden = receive("content-page-hidden", isData);
|
|
|
|
hiddenPage = await pageHidden;
|
|
is(interactiveDocument2, hiddenPage, "new document is hidden");
|
|
|
|
shownPage = await pageShown;
|
|
is(interactiveDocument1, shownPage, "previous document is shown");
|
|
|
|
info("load uri#3");
|
|
|
|
browser1.loadURI(uri3);
|
|
|
|
pageShown = receive("content-page-shown", isData);
|
|
|
|
let interactiveDocument3 = await documentInteractive;
|
|
|
|
let loadedDocument3 = await documentLoaded;
|
|
is(loadedDocument3.readyState, "complete", "document is loaded");
|
|
is(interactiveDocument3, loadedDocument3, "interactive document is loaded");
|
|
|
|
shownPage = await pageShown;
|
|
is(interactiveDocument3, shownPage, "previous document is shown");
|
|
|
|
gBrowser.removeTab(tab1);
|
|
|
|
info("load chrome uri");
|
|
|
|
const tab2 = openTab(uri4);
|
|
documentInteractive = receive("chrome-document-interactive", null, d => {
|
|
// This test is executed synchronously when the event is received.
|
|
is(d.readyState, "interactive", "document is interactive");
|
|
is(d.URL, uri4, "document.URL matches URL loaded");
|
|
});
|
|
documentLoaded = receive("chrome-document-loaded");
|
|
pageShown = receive("chrome-page-shown");
|
|
|
|
const interactiveDocument4 = await documentInteractive;
|
|
|
|
let loadedDocument4 = await documentLoaded;
|
|
is(loadedDocument4.readyState, "complete", "document is loaded");
|
|
is(interactiveDocument4, loadedDocument4, "interactive document is loaded");
|
|
|
|
shownPage = await pageShown;
|
|
is(interactiveDocument4, shownPage, "loaded chrome document is shown");
|
|
|
|
pageHidden = receive("chrome-page-hidden");
|
|
gBrowser.removeTab(tab2);
|
|
|
|
hiddenPage = await pageHidden;
|
|
is(interactiveDocument4, hiddenPage, "chrome document hidden");
|
|
});
|