summaryrefslogtreecommitdiffstats
path: root/dom/url/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/url/tests
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/url/tests')
-rw-r--r--dom/url/tests/browser.ini5
-rw-r--r--dom/url/tests/browser_download_after_revoke.js94
-rw-r--r--dom/url/tests/chrome.ini12
-rw-r--r--dom/url/tests/empty.html2
-rw-r--r--dom/url/tests/file_url.jsm24
-rw-r--r--dom/url/tests/file_worker_url.jsm23
-rw-r--r--dom/url/tests/jsm_url_worker.js84
-rw-r--r--dom/url/tests/mochitest.ini25
-rw-r--r--dom/url/tests/protocol_worker.js25
-rw-r--r--dom/url/tests/test_bloburl_location.html35
-rw-r--r--dom/url/tests/test_bug883784.jsm38
-rw-r--r--dom/url/tests/test_bug883784.xhtml34
-rw-r--r--dom/url/tests/test_unknown_url_origin.html17
-rw-r--r--dom/url/tests/test_url.html507
-rw-r--r--dom/url/tests/test_url.xhtml24
-rw-r--r--dom/url/tests/test_urlExceptions.html56
-rw-r--r--dom/url/tests/test_urlSearchParams.html59
-rw-r--r--dom/url/tests/test_urlSearchParams_sorting.html63
-rw-r--r--dom/url/tests/test_urlSearchParams_utf8.html39
-rw-r--r--dom/url/tests/test_url_data.html45
-rw-r--r--dom/url/tests/test_url_empty_port.html53
-rw-r--r--dom/url/tests/test_url_malformedHost.html48
-rw-r--r--dom/url/tests/test_urlutils_stringify.html38
-rw-r--r--dom/url/tests/test_worker_protocol.html41
-rw-r--r--dom/url/tests/test_worker_url.html66
-rw-r--r--dom/url/tests/test_worker_url.xhtml33
-rw-r--r--dom/url/tests/test_worker_urlApi.html43
-rw-r--r--dom/url/tests/test_worker_urlSearchParams.html43
-rw-r--r--dom/url/tests/test_worker_url_exceptions.html42
-rw-r--r--dom/url/tests/urlApi_worker.js354
-rw-r--r--dom/url/tests/urlSearchParams_commons.js376
-rw-r--r--dom/url/tests/urlSearchParams_worker.js48
-rw-r--r--dom/url/tests/url_exceptions_worker.js38
-rw-r--r--dom/url/tests/url_worker.js98
34 files changed, 2532 insertions, 0 deletions
diff --git a/dom/url/tests/browser.ini b/dom/url/tests/browser.ini
new file mode 100644
index 0000000000..ad58be9034
--- /dev/null
+++ b/dom/url/tests/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+ empty.html
+
+[browser_download_after_revoke.js]
diff --git a/dom/url/tests/browser_download_after_revoke.js b/dom/url/tests/browser_download_after_revoke.js
new file mode 100644
index 0000000000..be8ad96e70
--- /dev/null
+++ b/dom/url/tests/browser_download_after_revoke.js
@@ -0,0 +1,94 @@
+async function test() {
+ waitForExplicitFinish();
+ const target = "http://example.com/browser/dom/url/tests/empty.html";
+ info("Loading download page...");
+ let tab = BrowserTestUtils.addTab(gBrowser, target);
+ registerCleanupFunction(function () {
+ gBrowser.removeTab(tab);
+ window.restore();
+ });
+ gBrowser.selectedTab = tab;
+ BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, target).then(
+ async () => {
+ info("Page loaded.");
+ let allDownloads = await Downloads.getList(Downloads.ALL);
+ let started = new Promise(resolve => {
+ if (
+ Services.prefs.getBoolPref(
+ "browser.download.always_ask_before_handling_new_types",
+ false
+ )
+ ) {
+ // If the download modal is enabled, wait for it to open and declare the
+ // download to have begun when we see it.
+ let listener = {
+ onOpenWindow(aXULWindow) {
+ info("Download modal shown...");
+ Services.wm.removeListener(listener);
+
+ let domwindow = aXULWindow.docShell.domWindow;
+ function onModalLoad() {
+ domwindow.removeEventListener("load", onModalLoad, true);
+
+ is(
+ domwindow.document.location.href,
+ "chrome://mozapps/content/downloads/unknownContentType.xhtml",
+ "Download modal loaded..."
+ );
+
+ domwindow.close();
+ info("Download modal closed.");
+ resolve();
+ }
+
+ domwindow.addEventListener("load", onModalLoad, true);
+ },
+ onCloseWindow(aXULWindow) {},
+ };
+
+ Services.wm.addListener(listener);
+ } else {
+ // With no download modal, the download will begin on its own, so we need
+ // to wait to be notified by the downloads list when that happens.
+ let downloadView = {
+ onDownloadAdded(download) {
+ ok(true, "Download was started.");
+ download.cancel();
+ allDownloads.removeView(this);
+ allDownloads.removeFinished();
+ resolve();
+ },
+ };
+ allDownloads.addView(downloadView);
+ }
+ });
+
+ let revoked = SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ () =>
+ new Promise(resolve => {
+ info("Creating BlobURL...");
+ let blob = new content.Blob(["test"], { type: "text/plain" });
+ let url = content.URL.createObjectURL(blob);
+
+ let link = content.document.createElement("a");
+ link.href = url;
+ link.download = "example.txt";
+ content.document.body.appendChild(link);
+ info("Clicking HTMLAnchorElement...");
+ link.click();
+
+ content.URL.revokeObjectURL(url);
+ info("BlobURL revoked.");
+ resolve();
+ })
+ );
+
+ info("Waiting for async activities...");
+ await Promise.all([revoked, started]);
+ ok(true, "Exiting test.");
+ finish();
+ }
+ );
+}
diff --git a/dom/url/tests/chrome.ini b/dom/url/tests/chrome.ini
new file mode 100644
index 0000000000..1f1b9022c9
--- /dev/null
+++ b/dom/url/tests/chrome.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ file_url.jsm
+ file_worker_url.jsm
+ test_bug883784.jsm
+ jsm_url_worker.js
+ !/dom/workers/test/dom_worker_helper.js
+
+[test_bug883784.xhtml]
+[test_url.xhtml]
+[test_worker_url.xhtml]
diff --git a/dom/url/tests/empty.html b/dom/url/tests/empty.html
new file mode 100644
index 0000000000..358db717dd
--- /dev/null
+++ b/dom/url/tests/empty.html
@@ -0,0 +1,2 @@
+<!DOCTYPE HTML>
+<html><body></body></html>
diff --git a/dom/url/tests/file_url.jsm b/dom/url/tests/file_url.jsm
new file mode 100644
index 0000000000..6be99f2931
--- /dev/null
+++ b/dom/url/tests/file_url.jsm
@@ -0,0 +1,24 @@
+var EXPORTED_SYMBOLS = ["checkFromJSM"];
+
+function checkFromJSM(ok, is) {
+ var url = new URL("http://www.example.com");
+ is(url.href, "http://www.example.com/", "JSM should have URL");
+
+ var url2 = new URL("/foobar", url);
+ is(
+ url2.href,
+ "http://www.example.com/foobar",
+ "JSM should have URL - based on another URL"
+ );
+
+ var blob = new Blob(["a"]);
+ url = URL.createObjectURL(blob);
+ ok(url, "URL is created!");
+
+ var u = new URL(url);
+ ok(u, "URL created");
+ is(u.origin, "null", "Url doesn't have an origin if created in a JSM");
+
+ URL.revokeObjectURL(url);
+ ok(true, "URL is revoked");
+}
diff --git a/dom/url/tests/file_worker_url.jsm b/dom/url/tests/file_worker_url.jsm
new file mode 100644
index 0000000000..30a072ef9d
--- /dev/null
+++ b/dom/url/tests/file_worker_url.jsm
@@ -0,0 +1,23 @@
+var EXPORTED_SYMBOLS = ["checkFromJSM"];
+
+function checkFromJSM(ok, is, finish) {
+ let worker = new ChromeWorker("jsm_url_worker.js");
+ worker.onmessage = function (event) {
+ if (event.data.type == "finish") {
+ finish();
+ } else if (event.data.type == "url") {
+ URL.revokeObjectURL(event.data.url);
+ } else if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ }
+ };
+
+ worker.onerror = function (event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error: " + event.data);
+ worker.terminate();
+ finish();
+ };
+
+ worker.postMessage(0);
+}
diff --git a/dom/url/tests/jsm_url_worker.js b/dom/url/tests/jsm_url_worker.js
new file mode 100644
index 0000000000..d4cabe4113
--- /dev/null
+++ b/dom/url/tests/jsm_url_worker.js
@@ -0,0 +1,84 @@
+/* eslint-env worker */
+
+onmessage = function (event) {
+ if (event.data != 0) {
+ var worker = new Worker("jsm_url_worker.js");
+ worker.onmessage = function (ev) {
+ postMessage(ev.data);
+ };
+
+ worker.postMessage(event.data - 1);
+ return;
+ }
+
+ let status = false;
+ try {
+ if (URL instanceof Object) {
+ status = true;
+ }
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "URL object:" + URL });
+
+ status = false;
+ var blob = null;
+ try {
+ blob = new Blob([]);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob:" + blob });
+
+ status = false;
+ var url = null;
+ try {
+ url = URL.createObjectURL(blob);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob URL:" + url });
+
+ status = false;
+ try {
+ URL.revokeObjectURL(url);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob Revoke URL" });
+
+ status = false;
+ url = null;
+ try {
+ url = URL.createObjectURL(true);
+ } catch (e) {
+ status = true;
+ }
+
+ postMessage({
+ type: "status",
+ status,
+ msg: "CreateObjectURL should fail if the arg is not a blob",
+ });
+
+ status = false;
+ url = null;
+ try {
+ url = URL.createObjectURL(blob);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob URL2:" + url });
+
+ status = false;
+ try {
+ URL.createObjectURL({});
+ } catch (e) {
+ status = true;
+ }
+
+ postMessage({ type: "status", status, msg: "Exception wanted" });
+
+ postMessage({ type: "url", url });
+
+ postMessage({ type: "finish" });
+};
diff --git a/dom/url/tests/mochitest.ini b/dom/url/tests/mochitest.ini
new file mode 100644
index 0000000000..0e14b90ea9
--- /dev/null
+++ b/dom/url/tests/mochitest.ini
@@ -0,0 +1,25 @@
+[DEFAULT]
+support-files =
+ url_worker.js
+ urlApi_worker.js
+ urlSearchParams_commons.js
+ urlSearchParams_worker.js
+ url_exceptions_worker.js
+
+[test_url.html]
+[test_url_data.html]
+[test_url_empty_port.html]
+[test_url_malformedHost.html]
+[test_urlExceptions.html]
+[test_urlSearchParams.html]
+[test_urlSearchParams_sorting.html]
+[test_urlSearchParams_utf8.html]
+[test_urlutils_stringify.html]
+[test_worker_url.html]
+[test_worker_urlApi.html]
+[test_worker_url_exceptions.html]
+[test_worker_urlSearchParams.html]
+[test_unknown_url_origin.html]
+[test_bloburl_location.html]
+[test_worker_protocol.html]
+support-files = protocol_worker.js
diff --git a/dom/url/tests/protocol_worker.js b/dom/url/tests/protocol_worker.js
new file mode 100644
index 0000000000..c038254a4c
--- /dev/null
+++ b/dom/url/tests/protocol_worker.js
@@ -0,0 +1,25 @@
+function ok(a, msg) {
+ postMessage({ type: "status", status: !!a, msg });
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function finish() {
+ postMessage({ type: "finish" });
+}
+
+let url = new URL("http://example.com");
+is(url.protocol, "http:", "http: expected");
+
+url.protocol = "https:";
+is(url.protocol, "https:", "http: -> https:");
+
+url.protocol = "ftp:";
+is(url.protocol, "ftp:", "https: -> ftp:");
+
+url.protocol = "https:";
+is(url.protocol, "https:", "ftp: -> https:");
+
+finish();
diff --git a/dom/url/tests/test_bloburl_location.html b/dom/url/tests/test_bloburl_location.html
new file mode 100644
index 0000000000..f8442cffc5
--- /dev/null
+++ b/dom/url/tests/test_bloburl_location.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for blobURL in location</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script type="application/javascript">
+
+var expectedData = null;
+onmessage = function(e) {
+ if (expectedData === null) {
+ expectedData = e.data;
+ } else {
+ is(e.data, expectedData, "Pathname should be not be changed");
+ SimpleTest.finish();
+ }
+};
+
+SpecialPowers.pushPrefEnv({
+ "set": [["privacy.partition.bloburl_per_agent_cluster", false]]
+}).then(() => {
+ var ifr = document.createElement("iframe");
+ document.body.appendChild(ifr);
+
+ ifr.src = "data:text/html,<script>location=URL.createObjectURL(new%20Blob(['<script>parent.postMessage(location.pathname,\"*\");location.pathname=\"foo\";parent.postMessage(location.pathname,\"*\");<\/s' +'cript>'], {type:\"text/html\"}));<\/script>";
+});
+
+SimpleTest.waitForExplicitFinish();
+
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_bug883784.jsm b/dom/url/tests/test_bug883784.jsm
new file mode 100644
index 0000000000..1790007680
--- /dev/null
+++ b/dom/url/tests/test_bug883784.jsm
@@ -0,0 +1,38 @@
+var EXPORTED_SYMBOLS = ["Test"];
+
+var Test = {
+ start(ok, is, finish) {
+ let worker = new ChromeWorker("jsm_url_worker.js");
+ worker.onmessage = function (event) {
+ if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ } else if (event.data.type == "url") {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", event.data.url, false);
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState == 4) {
+ ok(true, "Blob readable!");
+ URL.revokeObjectURL(event.data.url);
+ finish();
+ }
+ };
+ xhr.onerror = function () {
+ ok(false, "Blob unreadable, should not happen!");
+ URL.revokeObjectURL(event.data.url);
+ finish();
+ };
+ xhr.send();
+ }
+ };
+
+ var self = this;
+ worker.onerror = function (event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error: " + event.data);
+ self.worker.terminate();
+ finish();
+ };
+
+ worker.postMessage(0);
+ },
+};
diff --git a/dom/url/tests/test_bug883784.xhtml b/dom/url/tests/test_bug883784.xhtml
new file mode 100644
index 0000000000..381eb08a37
--- /dev/null
+++ b/dom/url/tests/test_bug883784.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<window title="DOM Worker Threads Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="test();">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+ <script type="application/javascript" src="chrome://mochitests/content/chrome/dom/workers/test/dom_worker_helper.js"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+ /* import-globals-from ../../workers/test/dom_worker_helper.js */
+ function test()
+ {
+ waitForWorkerFinish();
+
+ const {Test} = ChromeUtils.import("chrome://mochitests/content/chrome/dom/url/tests/test_bug883784.jsm");
+ Test.start(ok, is, finish);
+ }
+
+ ]]>
+ </script>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <p id="display"></p>
+ <div id="content" style="display:none;"></div>
+ <pre id="test"></pre>
+ </body>
+ <label id="test-result"/>
+</window>
diff --git a/dom/url/tests/test_unknown_url_origin.html b/dom/url/tests/test_unknown_url_origin.html
new file mode 100644
index 0000000000..1c5571e9e4
--- /dev/null
+++ b/dom/url/tests/test_unknown_url_origin.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for unknwon URL.origin</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script type="application/javascript">
+
+ is((new URL("blob:http://foo.com/bar")).origin, "http://foo.com");
+ is((new URL("blob:blob:http://foo.com/bar")).origin, "http://foo.com");
+
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_url.html b/dom/url/tests/test_url.html
new file mode 100644
index 0000000000..85f39e54b9
--- /dev/null
+++ b/dom/url/tests/test_url.html
@@ -0,0 +1,507 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test URL API</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=887364">Mozilla Bug 887364</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=991471">Mozilla Bug 991471</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=996055">Mozilla Bug 996055</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+ <script>
+
+ /** Test for Bug 887364 **/
+ ok("URL" in window, "window.URL exists");
+
+ var tests = [
+ { url: "http://www.abc.com",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/",
+ origin: "http://www.abc.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/",
+ search: "",
+ hash: "",
+ },
+ { url: "ftp://auser:apw@www.abc.com",
+ base: undefined,
+ error: false,
+ href: "ftp://auser:apw@www.abc.com/",
+ origin: "ftp://www.abc.com",
+ protocol: "ftp:",
+ username: "auser",
+ password: "apw",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/",
+ search: "",
+ hash: "",
+ },
+ { url: "http://www.abc.com:90/apath/",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com:90/apath/",
+ origin: "http://www.abc.com:90",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com:90",
+ hostname: "www.abc.com",
+ port: "90",
+ pathname: "/apath/",
+ search: "",
+ hash: "",
+ },
+ { url: "http://www.abc.com/apath/afile.txt#ahash",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt#ahash",
+ origin: "http://www.abc.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/apath/afile.txt",
+ search: "",
+ hash: "#ahash",
+ },
+ { url: "http://example.com/?test#hash",
+ base: undefined,
+ error: false,
+ href: "http://example.com/?test#hash",
+ origin: "http://example.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "example.com",
+ hostname: "example.com",
+ port: "",
+ pathname: "/",
+ search: "?test",
+ hash: "#hash",
+ },
+ { url: "http://example.com/?test",
+ base: undefined,
+ error: false,
+ href: "http://example.com/?test",
+ origin: "http://example.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "example.com",
+ hostname: "example.com",
+ port: "",
+ pathname: "/",
+ search: "?test",
+ hash: "",
+ },
+ { url: "http://example.com/carrot#question%3f",
+ base: undefined,
+ error: false,
+ hash: "#question%3f",
+ },
+ { url: "https://example.com:4443?",
+ base: undefined,
+ error: false,
+ protocol: "https:",
+ port: "4443",
+ pathname: "/",
+ hash: "",
+ search: "",
+ },
+ { url: "http://www.abc.com/apath/afile.txt#ahash?asearch",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt#ahash?asearch",
+ protocol: "http:",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash?asearch",
+ search: "",
+ },
+ { url: "http://www.abc.com/apath/afile.txt?asearch#ahash",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt?asearch#ahash",
+ protocol: "http:",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "?asearch",
+ },
+ { url: "http://abc.com/apath/afile.txt?#ahash",
+ base: undefined,
+ error: false,
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "",
+ },
+ { url: "http://auser:apassword@www.abc.com:90/apath/afile.txt?asearch#ahash",
+ base: undefined,
+ error: false,
+ protocol: "http:",
+ username: "auser",
+ password: "apassword",
+ host: "www.abc.com:90",
+ hostname: "www.abc.com",
+ port: "90",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "?asearch",
+ origin: "http://www.abc.com:90",
+ },
+
+ { url: "/foo#bar",
+ base: "www.test.org",
+ error: true,
+ },
+ { url: "/foo#bar",
+ base: null,
+ error: true,
+ },
+ { url: "/foo#bar",
+ base: 42,
+ error: true,
+ },
+ { url: "ftp://ftp.something.net",
+ base: undefined,
+ error: false,
+ protocol: "ftp:",
+ },
+ { url: "file:///tmp/file",
+ base: undefined,
+ error: false,
+ protocol: "file:",
+ },
+ { url: "gopher://gopher.something.net",
+ base: undefined,
+ error: false,
+ protocol: "gopher:",
+ },
+ { url: "ws://ws.something.net",
+ base: undefined,
+ error: false,
+ protocol: "ws:",
+ },
+ { url: "wss://ws.something.net",
+ base: undefined,
+ error: false,
+ protocol: "wss:",
+ },
+ { url: "foo://foo.something.net",
+ base: undefined,
+ error: false,
+ protocol: "foo:",
+ },
+
+ { url: "about:blank",
+ base: undefined,
+ error: false,
+ protocol: "about:",
+ pathname: "blank",
+ skip_setters: false,
+ },
+
+ { url: "foo:bar?what#yeah",
+ base: undefined,
+ error: false,
+ protocol: "foo:",
+ pathname: "bar",
+ search: "?what",
+ hash: "#yeah",
+ skip_setters: false,
+ },
+
+ { url: "http://sub2.xn--lt-uia.mochi.test:8888/foo",
+ base: undefined,
+ error: false,
+ href: "http://sub2.xn--lt-uia.mochi.test:8888/foo",
+ origin: "http://sub2.xn--lt-uia.mochi.test:8888",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "sub2.xn--lt-uia.mochi.test:8888",
+ hostname: "sub2.xn--lt-uia.mochi.test",
+ port: "8888",
+ pathname: "/foo",
+ search: "",
+ hash: "",
+ },
+ { url: "http://sub2.ält.mochi.test:8888/foo",
+ base: undefined,
+ error: false,
+ href: "http://sub2.xn--lt-uia.mochi.test:8888/foo",
+ origin: "http://sub2.xn--lt-uia.mochi.test:8888",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "sub2.xn--lt-uia.mochi.test:8888",
+ hostname: "sub2.xn--lt-uia.mochi.test",
+ port: "8888",
+ pathname: "/foo",
+ search: "",
+ hash: "",
+ },
+ ];
+
+ while (tests.length) {
+ var test = tests.shift();
+
+ var error = false;
+ var url;
+ try {
+ if (test.base) {
+ url = new URL(test.url, test.base);
+ } else {
+ url = new URL(test.url);
+ }
+ } catch (e) {
+ error = true;
+ }
+
+ is(test.error, error, "Error creating URL");
+ if (test.error) {
+ continue;
+ }
+
+ if ("href" in test) is(url.href, test.href, "href");
+ if ("origin" in test) is(url.origin, test.origin, "origin");
+ if ("protocol" in test) is(url.protocol, test.protocol, "protocol");
+ if ("username" in test) is(url.username, test.username, "username");
+ if ("password" in test) is(url.password, test.password, "password");
+ if ("host" in test) is(url.host, test.host, "host");
+ if ("hostname" in test) is(url.hostname, test.hostname, "hostname");
+ if ("port" in test) is(url.port, test.port, "port");
+ if ("pathname" in test) is(url.pathname, test.pathname, "pathname");
+ if ("search" in test) is(url.search, test.search, "search");
+ if ("hash" in test) is(url.hash, test.hash, "hash");
+
+ {
+ let uri = SpecialPowers.wrap(url).URI;
+ is(url.href, uri.spec, "Conversion to nsIURI");
+ is(SpecialPowers.wrap(URL).fromURI(uri).href, uri.spec, "Conversion from nsIURI");
+ }
+
+ if ("skip_setters" in test && test.skip_setters === false) {
+ info("Skip setter methods for URL: " + test);
+ continue;
+ }
+
+ url = new URL("https://www.example.net/what#foo?bar");
+ ok(url, "Url exists!");
+
+ if ("href" in test) url.href = test.href;
+ if ("protocol" in test) url.protocol = test.protocol;
+ if ("username" in test && test.username) url.username = test.username;
+ if ("password" in test && test.password) url.password = test.password;
+ if ("host" in test) url.host = test.host;
+ if ("hostname" in test) url.hostname = test.hostname;
+ if ("port" in test) url.port = test.port;
+ if ("pathname" in test) url.pathname = test.pathname;
+ if ("search" in test) url.search = test.search;
+ if ("hash" in test) url.hash = test.hash;
+
+ if ("href" in test) is(url.href, test.href, "href");
+ if ("origin" in test) is(url.origin, test.origin, "origin");
+ if ("protocol" in test) is(url.protocol, test.protocol, "protocol");
+ if ("username" in test) is(url.username, test.username, "username");
+ if ("password" in test) is(url.password, test.password, "password");
+ if ("host" in test) is(url.host, test.host, "host");
+ if ("hostname" in test) is(test.hostname, url.hostname, "hostname");
+ if ("port" in test) is(test.port, url.port, "port");
+ if ("pathname" in test) is(test.pathname, url.pathname, "pathname");
+ if ("search" in test) is(test.search, url.search, "search");
+ if ("hash" in test) is(test.hash, url.hash, "hash");
+
+ if ("href" in test) is(test.href, url + "", "stringify works");
+ }
+
+ </script>
+
+ <script>
+ /** Test for Bug 991471 **/
+ var url = new URL("http://localhost/");
+ url.hostname = "";
+ url.username = "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt";
+ url.hostname = "www.mozilla.org";
+ url.username = "";
+ url.hostname = "www.mozilla.org";
+ is(url.href, "http://www.mozilla.org/", "No parsing error with empty host");
+ </script>
+
+ <script>
+ /** Test for Bug 996055 **/
+ var url = new URL("http://localhost/");
+ url.hostname = "";
+ is(url.href, "http://localhost/", "Empty hostname is ignored");
+ </script>
+
+ <script>
+ /** Test for Bug 960014 **/
+ var url = new URL("http://localhost/");
+ url.hostname = "[2001::1]";
+ is(url.hostname, "[2001::1]", "IPv6 hostname");
+ is(url.href, "http://[2001::1]/");
+
+ url.hostname = "[::192.9.5.5]";
+ is(url.hostname, "[::c009:505]", "IPv6 hostname");
+ is(url.href, "http://[::c009:505]/");
+
+ url = new URL("http://localhost/");
+ url.hostname = "[::]";
+ is(url.hostname, "[::]", "IPv6 hostname");
+
+ url = new URL("http://localhost/");
+ url.host = "[2001::1]:30";
+ is(url.hostname, "[2001::1]", "IPv6 hostname");
+ is(url.port, "30", "Port");
+ is(url.host, "[2001::1]:30", "IPv6 host");
+
+ url = new URL("http://localhost/");
+ // This should silently fail since it's missing the brackets
+ url.hostname = "2001::1";
+ is(url.hostname, "localhost", "Setting bad hostname fails");
+ </script>
+
+ <script>
+ var blob = new Blob(["a"]);
+ var url = URL.createObjectURL(blob);
+
+ var u = new URL(url);
+ is(u.origin, location.origin, "The URL generated from a blob URI has an origin");
+ </script>
+
+ <script>
+ var blob = new Blob(["a"]);
+ var url = URL.createObjectURL(blob);
+
+ var a = document.createElement("A");
+ a.href = url;
+ is(a.origin, location.origin, "The 'a' element has the correct origin");
+ </script>
+
+ <script>
+ var blob = new Blob(["a"]);
+ var url = URL.createObjectURL(blob);
+ URL.revokeObjectURL(url);
+ URL.revokeObjectURL(url);
+ ok(true, "Calling revokeObjectURL twice should be ok");
+ </script>
+
+ <script>
+ URL.revokeObjectURL("blob:something");
+ ok(true, "This should not throw.");
+ </script>
+
+ <script>
+ var base = new URL("http:\\\\test.com\\path/to\\file?query\\backslash#hash\\");
+ is(base.href, "http://test.com/path/to/file?query\\backslash#hash\\");
+
+ var url = new URL("..\\", base);
+ is(url.href, "http://test.com/path/");
+
+ url = new URL("\\test", base);
+ is(url.href, "http://test.com/test");
+
+ url = new URL("\\test\\", base);
+ is(url.href, "http://test.com/test/");
+
+ url = new URL("http://example.org/test", base);
+ is(url.href, "http://example.org/test");
+
+ url = new URL("ftp://tmp/test", base);
+ is(url.href, "ftp://tmp/test");
+
+ url = new URL("ftp:\\\\tmp\\test", base);
+ is(url.href, "ftp://tmp/test");
+
+ url = new URL("scheme://tmp\\test", base);
+ is(url.href, "scheme://tmp\\test");
+ </script>
+
+ <script>
+ /** Test for Bug 1275746 **/
+ SimpleTest.doesThrow(() => { new URL("http:"); }, "http: is not a valid URL");
+ SimpleTest.doesThrow(() => { new URL("http:///"); }, "http: is not a valid URL");
+
+ var url = new URL("file:");
+ is(url.href, "file:///", "Parsing file: should work.");
+
+ url = new URL("file:///");
+ is(url.href, "file:///", "Parsing file:/// should work.");
+ </script>
+
+ <script>
+ var url = new URL("scheme:path/to/file?query#hash");
+ is(url.href, "scheme:path/to/file?query#hash");
+ is(url.pathname, "path/to/file");
+ is(url.search, "?query");
+ is(url.hash, "#hash");
+
+ // pathname cannot be overwritten.
+ url.pathname = "new/path?newquery#newhash";
+ is(url.href, "scheme:path/to/file?query#hash");
+
+ // don't escape '#' until we implement a spec-compliant parser.
+ url.search = "?newquery#newhash";
+ is(url.href, "scheme:path/to/file?newquery#newhash#hash");
+
+ // nulls get encoded, whitespace gets stripped
+ url = new URL("scheme:pa\0\nth/to/fi\0\nle?qu\0\nery#ha\0\nsh");
+ is(url.href, "scheme:pa%00th/to/fi%00le?qu%00ery#ha%00sh");
+
+ url.search = "new\0\nquery";
+ is(url.href, "scheme:pa%00th/to/fi%00le?new%00%0Aquery#ha%00sh");
+ url.hash = "new\0\nhash";
+ is(url.href, "scheme:pa%00th/to/fi%00le?new%00%0Aquery#new%00%0Ahash");
+
+ url = new URL("scheme:path#hash");
+ is(url.href, "scheme:path#hash");
+ url.search = "query";
+ is(url.href, "scheme:path?query#hash");
+ url.hash = "";
+ is(url.href, "scheme:path?query");
+ url.hash = "newhash";
+ is(url.href, "scheme:path?query#newhash");
+ url.search = "";
+ is(url.href, "scheme:path#newhash");
+
+ // we don't implement a spec-compliant parser yet.
+ // make sure we are bug compatible with existing implementations.
+ url = new URL("data:text/html,<a href=\"http://example.org/?q\">Link</a>");
+ is(url.href, "data:text/html,<a href=\"http://example.org/?q\">Link</a>");
+ </script>
+
+ <script>
+ var u = new URL("http://www.example.org");
+ is(u.toJSON(), "http://www.example.org/", "URL.toJSON()");
+ is(JSON.stringify(u), "\"http://www.example.org/\"", "JSON.stringify(u) works");
+ </script>
+
+ <script>
+ // bug 1648493
+ var url = new URL("http://example.com/");
+ url.protocol = 'file'
+ url.protocol = 'resource'
+ url.password = 'ê'
+ url.username = 'ç'
+ url.protocol = 't'
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_url.xhtml b/dom/url/tests/test_url.xhtml
new file mode 100644
index 0000000000..10978c1f72
--- /dev/null
+++ b/dom/url/tests/test_url.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<window title="Test for URL API"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for URL API. **/
+ // Import our test JSM. We first strip the filename off
+ // the chrome url, then append the jsm filename.
+ var base = /.*\//.exec(window.location.href)[0];
+ const {checkFromJSM} = ChromeUtils.import(base + "file_url.jsm");
+
+ checkFromJSM(ok, is);
+
+ ]]></script>
+</window>
diff --git a/dom/url/tests/test_urlExceptions.html b/dom/url/tests/test_urlExceptions.html
new file mode 100644
index 0000000000..4feb30a948
--- /dev/null
+++ b/dom/url/tests/test_urlExceptions.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=926890
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 926890</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=926890">Mozilla Bug 926890</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+ <script type="application/javascript">
+
+ // URL.href throws
+ var url = new URL("http://www.example.com");
+ ok(url, "URL created");
+
+ try {
+ url.href = "42";
+ ok(false, "url.href = 42 should throw");
+ } catch (e) {
+ ok(true, "url.href = 42 should throw");
+ ok(e instanceof TypeError, "error type typeError");
+ }
+
+ url.href = "http://www.example.org";
+ ok(true, "url.href should not throw");
+
+ try {
+ new URL("42");
+ ok(false, "new URL(42) should throw");
+ } catch (e) {
+ ok(true, "new URL(42) should throw");
+ ok(e instanceof TypeError, "error type typeError");
+ }
+
+ try {
+ new URL("http://www.example.com", "42");
+ ok(false, "new URL(something, 42) should throw");
+ } catch (e) {
+ ok(true, "new URL(something, 42) should throw");
+ ok(e instanceof TypeError, "error type typeError");
+ }
+
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_urlSearchParams.html b/dom/url/tests/test_urlSearchParams.html
new file mode 100644
index 0000000000..d86959ab64
--- /dev/null
+++ b/dom/url/tests/test_urlSearchParams.html
@@ -0,0 +1,59 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=887836
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for URLSearchParams</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="urlSearchParams_commons.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=887836">Mozilla Bug 887836</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+<script type="application/javascript">
+
+ /** Test for Bug 887836 **/
+ ok("URLSearchParams" in window, "window.URLSearchParams exists");
+
+ var tests = [
+ testSimpleURLSearchParams,
+ testCopyURLSearchParams,
+ testParserURLSearchParams,
+ testURL,
+ testEncoding,
+ testOrdering,
+ testDelete,
+ testGetNULL,
+ testSet,
+ testIterable,
+ testZeroHandling,
+ testCopyConstructor,
+ testCTORs,
+ ];
+
+ function runTest() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ runTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/url/tests/test_urlSearchParams_sorting.html b/dom/url/tests/test_urlSearchParams_sorting.html
new file mode 100644
index 0000000000..a608e8bc13
--- /dev/null
+++ b/dom/url/tests/test_urlSearchParams_sorting.html
@@ -0,0 +1,63 @@
+
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for URLSearchParams.sort()</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript">
+
+function compareArray(a, b) {
+ is(a.length, b.length, "Length matches");
+ for (let i = 0; i < a.length; ++i) {
+ is(a[i], b[i], "Values " + i + " match");
+ }
+}
+
+[
+ {
+ "input": "z=b&a=b&z=a&a=a",
+ "output": [["a", "b"], ["a", "a"], ["z", "b"], ["z", "a"]],
+ },
+ {
+ "input": "\uFFFD=x&\uFFFC&\uFFFD=a",
+ "output": [["\uFFFC", ""], ["\uFFFD", "x"], ["\uFFFD", "a"]],
+ },
+ {
+ "input": "ffi&🌈", // 🌈 > code point, but < code unit because two code units
+ "output": [["🌈", ""], ["ffi", ""]],
+ },
+ {
+ "input": "é&e\uFFFD&e\u0301",
+ "output": [["e\u0301", ""], ["e\uFFFD", ""], ["é", ""]],
+ },
+ {
+ "input": "z=z&a=a&z=y&a=b&z=x&a=c&z=w&a=d&z=v&a=e&z=u&a=f&z=t&a=g",
+ "output": [["a", "a"], ["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["a", "f"], ["a", "g"], ["z", "z"], ["z", "y"], ["z", "x"], ["z", "w"], ["z", "v"], ["z", "u"], ["z", "t"]],
+ },
+].forEach((val) => {
+ info("Run test: " + JSON.stringify(val) + "\n");
+
+ let params = new URLSearchParams(val.input);
+ params.sort();
+
+ let i = 0;
+ for (let param of params) {
+ compareArray(param, val.output[i++]);
+ }
+
+ let url = new URL("?" + val.input, "https://example/");
+ url.searchParams.sort();
+ params = new URLSearchParams(url.search);
+ i = 0;
+ for (let param of params) {
+ compareArray(param, val.output[i++]);
+ }
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/url/tests/test_urlSearchParams_utf8.html b/dom/url/tests/test_urlSearchParams_utf8.html
new file mode 100644
index 0000000000..2a37b3b9a1
--- /dev/null
+++ b/dom/url/tests/test_urlSearchParams_utf8.html
@@ -0,0 +1,39 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1032511
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1032511</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1032511">Mozilla Bug 1032511</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+<a href="http://www.example.net?a=b&c=d" id="anchor">foobar</a>
+<area href="http://www.example.net?a=b&c=d" id="area">foobar</area>
+<script type="application/javascript">
+
+ /** Test for Bug 1032511 **/
+ var a = new URLSearchParams("%e2");
+ ok(a, "a exists");
+ is(a.toString(), "%EF%BF%BD=", "The value should be here.");
+
+ a = new URLSearchParams("a%e2");
+ is(a.toString(), "a%EF%BF%BD=", "The value should be here.");
+
+ a = new URLSearchParams("a%e2b");
+ is(a.toString(), "a%EF%BF%BDb=", "The value should be here.");
+
+</script>
+</body>
+</html>
diff --git a/dom/url/tests/test_url_data.html b/dom/url/tests/test_url_data.html
new file mode 100644
index 0000000000..a4d017936a
--- /dev/null
+++ b/dom/url/tests/test_url_data.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test URL API - data:plain</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1018682">Mozilla Bug 1018682</a>
+
+<script type="application/javascript">
+
+var base = new URL("data:text/plain,");
+
+let relative;
+try {
+ relative = new URL("a", base);
+ ok(false, "Relative URL from a data:text/plain should not work.");
+} catch (e) {
+ ok(true, "Relative URL from a data:text/plain should not work.");
+}
+
+base.protocol = "chrome:";
+is(base.protocol, "chrome:", "The protocol should be changed from data to chrome.");
+
+try {
+ relative = new URL("a", base);
+ ok(true, "Relative URL from a chrome: should work.");
+} catch (e) {
+ ok(false, "Relative URL from a chrome: should work.");
+}
+
+base.protocol = "http:";
+ok(true, "Protocol: http changed");
+is(base.href, "http://text/plain,", "Base URL is correct");
+
+relative = new URL("a", base);
+ok(relative, "This works.");
+is(relative.href, "http://text/a", "Relative URL is correct");
+
+</script>
+
+</body>
+</html>
diff --git a/dom/url/tests/test_url_empty_port.html b/dom/url/tests/test_url_empty_port.html
new file mode 100644
index 0000000000..5001bdfae5
--- /dev/null
+++ b/dom/url/tests/test_url_empty_port.html
@@ -0,0 +1,53 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=930450
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 930450</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=930450">Mozilla Bug 930450</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+ <a id="link" href="http://www.example.com:8080">foobar</a>
+ <area id="area" href="http://www.example.com:8080" />
+ <script type="application/javascript">
+
+ var url = new URL("http://www.example.com:8080");
+ is(url.port, "8080", "URL.port is 8080");
+ url.port = "";
+ is(url.port, "", "URL.port is ''");
+ url.port = 0;
+ is(url.port, "0", "URL.port is 0");
+
+ var link = document.getElementById("link");
+ is(link.port, "8080", "URL.port is 8080");
+ link.port = "";
+ is(link.href, "http://www.example.com/", "link.href matches");
+ is(link.port, "", "URL.port is ''");
+ link.port = 0;
+ is(link.href, "http://www.example.com:0/", "link.href matches");
+ is(link.port, "0", "URL.port is 0");
+
+ var area = document.getElementById("area");
+ is(area.port, "8080", "URL.port is 8080");
+ area.port = "";
+ is(area.href, "http://www.example.com/", "area.href matches");
+ is(area.port, "", "URL.port is ''");
+ area.port = 0;
+ is(area.href, "http://www.example.com:0/", "area.href matches");
+ is(area.port, "0", "URL.port is 0");
+
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_url_malformedHost.html b/dom/url/tests/test_url_malformedHost.html
new file mode 100644
index 0000000000..7cc23d7e32
--- /dev/null
+++ b/dom/url/tests/test_url_malformedHost.html
@@ -0,0 +1,48 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1020041
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1020041</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020041">Mozilla Bug 1020041</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+ <a id="link" href="http://www.example.com:8080">foobar</a>
+ <area id="area" href="http://www.example.com:8080" />
+ <script type="application/javascript">
+
+ var tests = [
+ { host: "?", expected: "www.example.com" },
+ { host: "what?", expected: "what" },
+ { host: "so what", expected: "www.example.com" },
+ { host: "aa#bb", expected: "aa" },
+ { host: "a/b", expected: "a" },
+ { host: "a\\b", expected: "a" },
+ { host: "[2001::1]#bla:10", expected: "[2001::1]"},
+ ];
+
+ for (var i = 0; i < tests.length; ++i) {
+ var url = new URL("http://www.example.com");
+ url.host = tests[i].host;
+ is(url.host, tests[i].expected, "URL.host is: " + url.host);
+
+ url = new URL("http://www.example.com");
+ url.hostname = tests[i].host;
+ is(url.hostname, tests[i].expected, "URL.hostname is: " + url.host);
+ }
+
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_urlutils_stringify.html b/dom/url/tests/test_urlutils_stringify.html
new file mode 100644
index 0000000000..7c68051535
--- /dev/null
+++ b/dom/url/tests/test_urlutils_stringify.html
@@ -0,0 +1,38 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=959190
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 959190</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=959190">Mozilla Bug 959190</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="x" id="x"></iframe>
+ <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+ <a id="link" href="http://www.example.com:8080">foobar</a>
+ <area id="area" href="http://www.example.com:8080" />
+ <script type="application/javascript">
+
+ var url = new URL("http://www.example.com:8080");
+ is(url + "", "http://www.example.com:8080/", "URL stringify");
+
+ var link = document.getElementById("link");
+ is(link + "", "http://www.example.com:8080/", "Anchor stringify");
+
+ var area = document.getElementById("area");
+ is(area + "", "http://www.example.com:8080/", "Area stringify");
+
+ is((location + "").indexOf(`${location.origin}/tests/dom/url/tests/test_urlutils_stringify.html`), 0, "Location stringify");
+ </script>
+</body>
+</html>
diff --git a/dom/url/tests/test_worker_protocol.html b/dom/url/tests/test_worker_protocol.html
new file mode 100644
index 0000000000..1687159d6a
--- /dev/null
+++ b/dom/url/tests/test_worker_protocol.html
@@ -0,0 +1,41 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for URL protocol setter in workers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+ let worker = new Worker("protocol_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker, "Correct worker");
+
+ if (event.data.type == "finish") {
+ SimpleTest.finish();
+ return;
+ }
+
+ if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ return;
+ }
+
+ ok(false, "Invalid message.");
+ };
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/url/tests/test_worker_url.html b/dom/url/tests/test_worker_url.html
new file mode 100644
index 0000000000..8bcd265d19
--- /dev/null
+++ b/dom/url/tests/test_worker_url.html
@@ -0,0 +1,66 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for URL object in workers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("url_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker, "Correct worker");
+
+ if (event.data.type == "finish") {
+ runTest();
+ } else if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ } else if (event.data.type == "url") {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", event.data.url, false);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ ok(true, "Blob readable!");
+ }
+ };
+ xhr.send();
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker, "Correct worker");
+ ok(false, "Worker had an error: " + event.message);
+ SimpleTest.finish();
+ };
+
+ var tests = [
+ function() { worker.postMessage(0); },
+ function() { worker.postMessage(1); },
+ ];
+
+ function runTest() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+ }
+
+ runTest();
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/url/tests/test_worker_url.xhtml b/dom/url/tests/test_worker_url.xhtml
new file mode 100644
index 0000000000..30d2aa131d
--- /dev/null
+++ b/dom/url/tests/test_worker_url.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<window title="DOM Worker Threads Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="test();">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+
+ function test()
+ {
+ SimpleTest.waitForExplicitFinish();
+
+ const {checkFromJSM} = ChromeUtils.import("chrome://mochitests/content/chrome/dom/url/tests/file_worker_url.jsm");
+ checkFromJSM(ok, is, SimpleTest.finish);
+ }
+
+ ]]>
+ </script>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <p id="display"></p>
+ <div id="content" style="display:none;"></div>
+ <pre id="test"></pre>
+ </body>
+ <label id="test-result"/>
+</window>
diff --git a/dom/url/tests/test_worker_urlApi.html b/dom/url/tests/test_worker_urlApi.html
new file mode 100644
index 0000000000..34de982ef1
--- /dev/null
+++ b/dom/url/tests/test_worker_urlApi.html
@@ -0,0 +1,43 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for URL API object in workers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("urlApi_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker);
+
+ if (event.data.type == "finish") {
+ SimpleTest.finish();
+ } else if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error: " + event.data);
+ SimpleTest.finish();
+ };
+
+ worker.postMessage(true);
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/url/tests/test_worker_urlSearchParams.html b/dom/url/tests/test_worker_urlSearchParams.html
new file mode 100644
index 0000000000..1870d5d7dc
--- /dev/null
+++ b/dom/url/tests/test_worker_urlSearchParams.html
@@ -0,0 +1,43 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for URLSearchParams object in workers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("urlSearchParams_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker);
+
+ if (event.data.type == "finish") {
+ SimpleTest.finish();
+ } else if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error: " + event.message);
+ SimpleTest.finish();
+ };
+
+ worker.postMessage(true);
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/url/tests/test_worker_url_exceptions.html b/dom/url/tests/test_worker_url_exceptions.html
new file mode 100644
index 0000000000..2c8b493bbf
--- /dev/null
+++ b/dom/url/tests/test_worker_url_exceptions.html
@@ -0,0 +1,42 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for URL exceptions in workers</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+ var worker = new Worker("url_exceptions_worker.js");
+
+ worker.onmessage = function(event) {
+ is(event.target, worker);
+
+ if (event.data.type == "finish") {
+ SimpleTest.finish();
+ } else if (event.data.type == "status") {
+ ok(event.data.status, event.data.msg);
+ }
+ };
+
+ worker.onerror = function(event) {
+ is(event.target, worker);
+ ok(false, "Worker had an error: " + event.message);
+ SimpleTest.finish();
+ };
+
+ worker.postMessage(0);
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/url/tests/urlApi_worker.js b/dom/url/tests/urlApi_worker.js
new file mode 100644
index 0000000000..40243c1e66
--- /dev/null
+++ b/dom/url/tests/urlApi_worker.js
@@ -0,0 +1,354 @@
+/* eslint-env worker */
+
+function ok(a, msg) {
+ dump("OK: " + !!a + " => " + a + " " + msg + "\n");
+ postMessage({ type: "status", status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+ dump("IS: " + (a === b) + " => " + a + " | " + b + " " + msg + "\n");
+ postMessage({
+ type: "status",
+ status: a === b,
+ msg: a + " === " + b + ": " + msg,
+ });
+}
+
+// eslint-disable-next-line complexity
+onmessage = function () {
+ let status = false;
+ try {
+ if (URL instanceof Object) {
+ status = true;
+ }
+ } catch (e) {}
+
+ ok(status, "URL in workers \\o/");
+
+ var tests = [
+ {
+ url: "http://www.abc.com",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/",
+ origin: "http://www.abc.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/",
+ search: "",
+ hash: "",
+ },
+ {
+ url: "ftp://auser:apw@www.abc.com",
+ base: undefined,
+ error: false,
+ href: "ftp://auser:apw@www.abc.com/",
+ origin: "ftp://www.abc.com",
+ protocol: "ftp:",
+ username: "auser",
+ password: "apw",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/",
+ search: "",
+ hash: "",
+ },
+ {
+ url: "http://www.abc.com:90/apath/",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com:90/apath/",
+ origin: "http://www.abc.com:90",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com:90",
+ hostname: "www.abc.com",
+ port: "90",
+ pathname: "/apath/",
+ search: "",
+ hash: "",
+ },
+ {
+ url: "http://www.abc.com/apath/afile.txt#ahash",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt#ahash",
+ origin: "http://www.abc.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "www.abc.com",
+ hostname: "www.abc.com",
+ port: "",
+ pathname: "/apath/afile.txt",
+ search: "",
+ hash: "#ahash",
+ },
+ {
+ url: "http://example.com/?test#hash",
+ base: undefined,
+ error: false,
+ href: "http://example.com/?test#hash",
+ origin: "http://example.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "example.com",
+ hostname: "example.com",
+ port: "",
+ pathname: "/",
+ search: "?test",
+ hash: "#hash",
+ },
+ {
+ url: "http://example.com/?test",
+ base: undefined,
+ error: false,
+ href: "http://example.com/?test",
+ origin: "http://example.com",
+ protocol: "http:",
+ username: "",
+ password: "",
+ host: "example.com",
+ hostname: "example.com",
+ port: "",
+ pathname: "/",
+ search: "?test",
+ hash: "",
+ },
+ {
+ url: "http://example.com/carrot#question%3f",
+ base: undefined,
+ error: false,
+ hash: "#question%3f",
+ },
+ {
+ url: "https://example.com:4443?",
+ base: undefined,
+ error: false,
+ protocol: "https:",
+ port: "4443",
+ pathname: "/",
+ hash: "",
+ search: "",
+ },
+ {
+ url: "http://www.abc.com/apath/afile.txt#ahash?asearch",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt#ahash?asearch",
+ protocol: "http:",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash?asearch",
+ search: "",
+ },
+ {
+ url: "http://www.abc.com/apath/afile.txt?asearch#ahash",
+ base: undefined,
+ error: false,
+ href: "http://www.abc.com/apath/afile.txt?asearch#ahash",
+ protocol: "http:",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "?asearch",
+ },
+ {
+ url: "http://abc.com/apath/afile.txt?#ahash",
+ base: undefined,
+ error: false,
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "",
+ },
+ {
+ url: "http://auser:apassword@www.abc.com:90/apath/afile.txt?asearch#ahash",
+ base: undefined,
+ error: false,
+ protocol: "http:",
+ username: "auser",
+ password: "apassword",
+ host: "www.abc.com:90",
+ hostname: "www.abc.com",
+ port: "90",
+ pathname: "/apath/afile.txt",
+ hash: "#ahash",
+ search: "?asearch",
+ origin: "http://www.abc.com:90",
+ },
+
+ { url: "/foo#bar", base: "www.test.org", error: true },
+ { url: "/foo#bar", base: null, error: true },
+ { url: "/foo#bar", base: 42, error: true },
+ {
+ url: "ftp://ftp.something.net",
+ base: undefined,
+ error: false,
+ protocol: "ftp:",
+ },
+ {
+ url: "file:///tmp/file",
+ base: undefined,
+ error: false,
+ protocol: "file:",
+ },
+ {
+ url: "gopher://gopher.something.net",
+ base: undefined,
+ error: false,
+ protocol: "gopher:",
+ },
+ {
+ url: "ws://ws.something.net",
+ base: undefined,
+ error: false,
+ protocol: "ws:",
+ },
+ {
+ url: "wss://ws.something.net",
+ base: undefined,
+ error: false,
+ protocol: "wss:",
+ },
+ {
+ url: "foo://foo.something.net",
+ base: undefined,
+ error: false,
+ protocol: "foo:",
+ },
+ ];
+
+ while (tests.length) {
+ var test = tests.shift();
+
+ var error = false;
+ var url;
+ try {
+ if (test.base) {
+ url = new URL(test.url, test.base);
+ } else {
+ url = new URL(test.url);
+ }
+ } catch (e) {
+ error = true;
+ }
+
+ is(test.error, error, "Error creating URL");
+ if (test.error) {
+ continue;
+ }
+
+ if ("href" in test) {
+ is(url.href, test.href, "href");
+ }
+ if ("origin" in test) {
+ is(url.origin, test.origin, "origin");
+ }
+ if ("protocol" in test) {
+ is(url.protocol, test.protocol, "protocol");
+ }
+ if ("username" in test) {
+ is(url.username, test.username, "username");
+ }
+ if ("password" in test) {
+ is(url.password, test.password, "password");
+ }
+ if ("host" in test) {
+ is(url.host, test.host, "host");
+ }
+ if ("hostname" in test) {
+ is(url.hostname, test.hostname, "hostname");
+ }
+ if ("port" in test) {
+ is(url.port, test.port, "port");
+ }
+ if ("pathname" in test) {
+ is(url.pathname, test.pathname, "pathname");
+ }
+ if ("search" in test) {
+ is(url.search, test.search, "search");
+ }
+ if ("hash" in test) {
+ is(url.hash, test.hash, "hash");
+ }
+
+ url = new URL("https://www.example.net/what#foo?bar");
+ ok(url, "Url exists!");
+
+ if ("href" in test) {
+ url.href = test.href;
+ }
+ if ("protocol" in test) {
+ url.protocol = test.protocol;
+ }
+ if ("username" in test && test.username) {
+ url.username = test.username;
+ }
+ if ("password" in test && test.password) {
+ url.password = test.password;
+ }
+ if ("host" in test) {
+ url.host = test.host;
+ }
+ if ("hostname" in test) {
+ url.hostname = test.hostname;
+ }
+ if ("port" in test) {
+ url.port = test.port;
+ }
+ if ("pathname" in test) {
+ url.pathname = test.pathname;
+ }
+ if ("search" in test) {
+ url.search = test.search;
+ }
+ if ("hash" in test) {
+ url.hash = test.hash;
+ }
+
+ if ("href" in test) {
+ is(url.href, test.href, "href");
+ }
+ if ("origin" in test) {
+ is(url.origin, test.origin, "origin");
+ }
+ if ("protocol" in test) {
+ is(url.protocol, test.protocol, "protocol");
+ }
+ if ("username" in test) {
+ is(url.username, test.username, "username");
+ }
+ if ("password" in test) {
+ is(url.password, test.password, "password");
+ }
+ if ("host" in test) {
+ is(url.host, test.host, "host");
+ }
+ if ("hostname" in test) {
+ is(test.hostname, url.hostname, "hostname");
+ }
+ if ("port" in test) {
+ is(test.port, url.port, "port");
+ }
+ if ("pathname" in test) {
+ is(test.pathname, url.pathname, "pathname");
+ }
+ if ("search" in test) {
+ is(test.search, url.search, "search");
+ }
+ if ("hash" in test) {
+ is(test.hash, url.hash, "hash");
+ }
+
+ if ("href" in test) {
+ is(test.href, url + "", "stringify works");
+ }
+ }
+
+ postMessage({ type: "finish" });
+};
diff --git a/dom/url/tests/urlSearchParams_commons.js b/dom/url/tests/urlSearchParams_commons.js
new file mode 100644
index 0000000000..3a1dcb2807
--- /dev/null
+++ b/dom/url/tests/urlSearchParams_commons.js
@@ -0,0 +1,376 @@
+/* import-globals-from urlSearchParams_worker.js */
+
+function testSimpleURLSearchParams() {
+ var u = new URLSearchParams();
+ ok(u, "URLSearchParams created");
+ is(u.has("foo"), false, "URLSearchParams.has(foo)");
+ is(u.get("foo"), null, "URLSearchParams.get(foo)");
+ is(u.getAll("foo").length, 0, "URLSearchParams.getAll(foo)");
+
+ u.append("foo", "bar");
+ is(u.has("foo"), true, "URLSearchParams.has(foo)");
+ is(u.get("foo"), "bar", "URLSearchParams.get(foo)");
+ is(u.getAll("foo").length, 1, "URLSearchParams.getAll(foo)");
+
+ u.set("foo", "bar2");
+ is(u.get("foo"), "bar2", "URLSearchParams.get(foo)");
+ is(u.getAll("foo").length, 1, "URLSearchParams.getAll(foo)");
+
+ is(u + "", "foo=bar2", "stringifier");
+
+ u.delete("foo");
+
+ runTest();
+}
+
+function testCopyURLSearchParams() {
+ var u = new URLSearchParams();
+ ok(u, "URLSearchParams created");
+ u.append("foo", "bar");
+
+ var uu = new URLSearchParams(u);
+ is(uu.get("foo"), "bar", "uu.get()");
+
+ u.append("foo", "bar2");
+ is(u.getAll("foo").length, 2, "u.getAll()");
+ is(uu.getAll("foo").length, 1, "uu.getAll()");
+
+ runTest();
+}
+
+function testURL() {
+ var url = new URL("http://www.example.net?a=b&c=d");
+ ok(url.searchParams, "URL searchParams exists!");
+ ok(url.searchParams.has("a"), "URL.searchParams.has('a')");
+ is(url.searchParams.get("a"), "b", "URL.searchParams.get('a')");
+ ok(url.searchParams.has("c"), "URL.searchParams.has('c')");
+ is(url.searchParams.get("c"), "d", "URL.searchParams.get('c')");
+
+ url.searchParams.set("e", "f");
+ ok(url.href.indexOf("e=f") != 1, "URL right");
+
+ url = new URL("mailto:a@b.com?subject=Hi");
+ ok(url.searchParams, "URL searchParams exists!");
+ ok(url.searchParams.has("subject"), "Hi");
+
+ runTest();
+}
+
+function testParserURLSearchParams() {
+ var checks = [
+ { input: "", data: {} },
+ { input: "a", data: { a: [""] } },
+ { input: "a=b", data: { a: ["b"] } },
+ { input: "a=", data: { a: [""] } },
+ { input: "=b", data: { "": ["b"] } },
+ { input: "&", data: {} },
+ { input: "&a", data: { a: [""] } },
+ { input: "a&", data: { a: [""] } },
+ { input: "a&a", data: { a: ["", ""] } },
+ { input: "a&b&c", data: { a: [""], b: [""], c: [""] } },
+ { input: "a=b&c=d", data: { a: ["b"], c: ["d"] } },
+ { input: "a=b&c=d&", data: { a: ["b"], c: ["d"] } },
+ { input: "&&&a=b&&&&c=d&", data: { a: ["b"], c: ["d"] } },
+ { input: "a=a&a=b&a=c", data: { a: ["a", "b", "c"] } },
+ { input: "a==a", data: { a: ["=a"] } },
+ { input: "a=a+b+c+d", data: { a: ["a b c d"] } },
+ { input: "%=a", data: { "%": ["a"] } },
+ { input: "%a=a", data: { "%a": ["a"] } },
+ { input: "%a_=a", data: { "%a_": ["a"] } },
+ { input: "%61=a", data: { a: ["a"] } },
+ { input: "%=a", data: { "%": ["a"] } },
+ { input: "%a=a", data: { "%a": ["a"] } },
+ { input: "%a_=a", data: { "%a_": ["a"] } },
+ { input: "%61=a", data: { a: ["a"] } },
+ { input: "%61+%4d%4D=", data: { "a MM": [""] } },
+ { input: "?a=1", data: { a: ["1"] } },
+ { input: "?", data: {} },
+ { input: "?=b", data: { "": ["b"] } },
+ ];
+
+ for (var i = 0; i < checks.length; ++i) {
+ var u = new URLSearchParams(checks[i].input);
+
+ var count = 0;
+ for (var key in checks[i].data) {
+ count = count + 1;
+ ok(u.has(key), "key " + key + " found");
+
+ var all = u.getAll(key);
+ is(all.length, checks[i].data[key].length, "same number of elements");
+
+ for (var k = 0; k < all.length; ++k) {
+ is(all[k], checks[i].data[key][k], "value matches");
+ }
+ }
+ }
+
+ runTest();
+}
+
+function testEncoding() {
+ var encoding = [
+ ["1", "1"],
+ ["a b", "a+b"],
+ ["<>", "%3C%3E"],
+ ["\u0541", "%D5%81"],
+ ];
+
+ for (var i = 0; i < encoding.length; ++i) {
+ var url = new URL("http://www.example.net");
+ url.searchParams.set("a", encoding[i][0]);
+ is(url.href, "http://www.example.net/?a=" + encoding[i][1]);
+
+ var url2 = new URL(url.href);
+ is(url2.searchParams.get("a"), encoding[i][0], "a is still there");
+ }
+
+ runTest();
+}
+
+function testCopyConstructor() {
+ var url = new URL("http://example.com/");
+ var p = url.searchParams;
+ var q = new URLSearchParams(p);
+ q.set("a", "b");
+ is(
+ url.href,
+ "http://example.com/",
+ "Messing with copy of URLSearchParams should not affect URL"
+ );
+ p.set("c", "d");
+ is(
+ url.href,
+ "http://example.com/?c=d",
+ "Messing with URLSearchParams should affect URL"
+ );
+
+ runTest();
+}
+
+function testOrdering() {
+ var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6");
+ is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct");
+ is(a.getAll("a").length, 3, "Correct length of getAll()");
+
+ var b = new URLSearchParams();
+ b.append("a", "1");
+ b.append("b", "2");
+ b.append("a", "3");
+ is(b.toString(), "a=1&b=2&a=3", "Order is correct");
+ is(b.getAll("a").length, 2, "Correct length of getAll()");
+
+ runTest();
+}
+
+function testDelete() {
+ var a = new URLSearchParams("a=1&a=2&b=3&c=4&c=5&a=6");
+ is(a.toString(), "a=1&a=2&b=3&c=4&c=5&a=6", "Order is correct");
+ is(a.getAll("a").length, 3, "Correct length of getAll()");
+
+ a.delete("a");
+ is(a.getAll("a").length, 0, "Correct length of getAll()");
+ is(a.toString(), "b=3&c=4&c=5", "Order is correct");
+
+ runTest();
+}
+
+function testGetNULL() {
+ var u = new URLSearchParams();
+ is(typeof u.get(""), "object", "typeof URL.searchParams.get('')");
+ is(u.get(""), null, "URL.searchParams.get('') should be null");
+
+ var url = new URL("http://www.example.net?a=b");
+ is(
+ url.searchParams.get("b"),
+ null,
+ "URL.searchParams.get('b') should be null"
+ );
+ is(url.searchParams.get("a"), "b", "URL.searchParams.get('a')");
+
+ runTest();
+}
+
+function testSet() {
+ var u = new URLSearchParams();
+ u.set("a", "b");
+ u.set("e", "c");
+ u.set("i", "d");
+ u.set("o", "f");
+ u.set("u", "g");
+
+ is(u.get("a"), "b", "URL.searchParams.get('a') should return b");
+ is(u.getAll("a").length, 1, "URLSearchParams.getAll('a').length should be 1");
+
+ u.set("a", "h1");
+ u.set("a", "h2");
+ u.set("a", "h3");
+ u.set("a", "h4");
+ is(u.get("a"), "h4", "URL.searchParams.get('a') should return h4");
+ is(u.getAll("a").length, 1, "URLSearchParams.getAll('a').length should be 1");
+
+ is(u.get("e"), "c", "URL.searchParams.get('e') should return c");
+ is(u.get("i"), "d", "URL.searchParams.get('i') should return d");
+ is(u.get("o"), "f", "URL.searchParams.get('o') should return f");
+ is(u.get("u"), "g", "URL.searchParams.get('u') should return g");
+
+ is(u.getAll("e").length, 1, "URLSearchParams.getAll('e').length should be 1");
+ is(u.getAll("i").length, 1, "URLSearchParams.getAll('i').length should be 1");
+ is(u.getAll("o").length, 1, "URLSearchParams.getAll('o').length should be 1");
+ is(u.getAll("u").length, 1, "URLSearchParams.getAll('u').length should be 1");
+
+ u = new URLSearchParams("name1=value1&name1=value2&name1=value3");
+ is(
+ u.get("name1"),
+ "value1",
+ "URL.searchParams.get('name1') should return value1"
+ );
+ is(
+ u.getAll("name1").length,
+ 3,
+ "URLSearchParams.getAll('name1').length should be 3"
+ );
+ u.set("name1", "firstPair");
+ is(
+ u.get("name1"),
+ "firstPair",
+ "URL.searchParams.get('name1') should return firstPair"
+ );
+ is(
+ u.getAll("name1").length,
+ 1,
+ "URLSearchParams.getAll('name1').length should be 1"
+ );
+
+ runTest();
+}
+
+function testIterable() {
+ var u = new URLSearchParams();
+ u.set("1", "2");
+ u.set("2", "4");
+ u.set("3", "6");
+ u.set("4", "8");
+ u.set("5", "10");
+
+ var key_iter = u.keys();
+ var value_iter = u.values();
+ var entries_iter = u.entries();
+ for (var i = 0; i < 5; ++i) {
+ var v = i + 1;
+ var key = key_iter.next();
+ var value = value_iter.next();
+ var entry = entries_iter.next();
+ is(key.value, v.toString(), "Correct Key iterator: " + v.toString());
+ ok(!key.done, "Key.done is false");
+ is(
+ value.value,
+ (v * 2).toString(),
+ "Correct Value iterator: " + (v * 2).toString()
+ );
+ ok(!value.done, "Value.done is false");
+ is(
+ entry.value[0],
+ v.toString(),
+ "Correct Entry 0 iterator: " + v.toString()
+ );
+ is(
+ entry.value[1],
+ (v * 2).toString(),
+ "Correct Entry 1 iterator: " + (v * 2).toString()
+ );
+ ok(!entry.done, "Entry.done is false");
+ }
+
+ var last = key_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last key");
+
+ last = value_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last value");
+
+ last = entries_iter.next();
+ ok(last.done, "Nothing more to read.");
+
+ key_iter = u.keys();
+ key_iter.next();
+ key_iter.next();
+ u.delete("1");
+ u.delete("2");
+ u.delete("3");
+ u.delete("4");
+ u.delete("5");
+
+ last = key_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last key");
+
+ runTest();
+}
+function testZeroHandling() {
+ var u = new URLSearchParams();
+ u.set("a", "b\0c");
+ u.set("d\0e", "f");
+ u.set("g\0h", "i\0j");
+ is(
+ u.toString(),
+ "a=b%00c&d%00e=f&g%00h=i%00j",
+ "Should encode U+0000 as %00"
+ );
+
+ runTest();
+}
+
+function testCTORs() {
+ var a = new URLSearchParams("a=b");
+ is(a.get("a"), "b", "CTOR with string");
+
+ var b = new URLSearchParams([
+ ["a", "b"],
+ ["c", "d"],
+ ]);
+ is(b.get("a"), "b", "CTOR with sequence");
+ is(b.get("c"), "d", "CTOR with sequence");
+
+ ok(new URLSearchParams([]), "CTOR with empty sequence");
+
+ let result;
+ try {
+ result = new URLSearchParams([[1]]);
+ } catch (e) {
+ result = 42;
+ }
+
+ is(
+ result,
+ 42,
+ "CTOR throws if the sequence doesn't contain exactly 2 elements"
+ );
+
+ try {
+ result = new URLSearchParams([[1, 2, 3]]);
+ } catch (e) {
+ result = 43;
+ }
+ is(
+ result,
+ 43,
+ "CTOR throws if the sequence doesn't contain exactly 2 elements"
+ );
+
+ var c = new URLSearchParams({
+ a: "b",
+ c: 42,
+ d: null,
+ e: [1, 2, 3],
+ f: { a: 42 },
+ });
+ is(c.get("a"), "b", "CTOR with record<>");
+ is(c.get("c"), "42", "CTOR with record<>");
+ is(c.get("d"), "null", "CTOR with record<>");
+ is(c.get("e"), [1, 2, 3].toString(), "CTOR with record<>");
+ is(c.get("f"), { a: 42 }.toString(), "CTOR with record<>");
+
+ runTest();
+}
diff --git a/dom/url/tests/urlSearchParams_worker.js b/dom/url/tests/urlSearchParams_worker.js
new file mode 100644
index 0000000000..7959fd7d1c
--- /dev/null
+++ b/dom/url/tests/urlSearchParams_worker.js
@@ -0,0 +1,48 @@
+/* eslint-env worker */
+
+importScripts("urlSearchParams_commons.js");
+
+function ok(a, msg) {
+ dump("OK: " + !!a + " => " + a + " " + msg + "\n");
+ postMessage({ type: "status", status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+ dump("IS: " + (a === b) + " => " + a + " | " + b + " " + msg + "\n");
+ postMessage({
+ type: "status",
+ status: a === b,
+ msg: a + " === " + b + ": " + msg,
+ });
+}
+
+var tests = [
+ testSimpleURLSearchParams,
+ testCopyURLSearchParams,
+ testParserURLSearchParams,
+ testURL,
+ testEncoding,
+ testCTORs,
+];
+
+function runTest() {
+ if (!tests.length) {
+ postMessage({ type: "finish" });
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+onmessage = function () {
+ let status = false;
+ try {
+ if (URLSearchParams instanceof Object) {
+ status = true;
+ }
+ } catch (e) {}
+ ok(status, "URLSearchParams in workers \\o/");
+
+ runTest();
+};
diff --git a/dom/url/tests/url_exceptions_worker.js b/dom/url/tests/url_exceptions_worker.js
new file mode 100644
index 0000000000..c8d8494ac9
--- /dev/null
+++ b/dom/url/tests/url_exceptions_worker.js
@@ -0,0 +1,38 @@
+function ok(a, msg) {
+ postMessage({ type: "status", status: !!a, msg });
+}
+
+onmessage = function (event) {
+ // URL.href throws
+ var url = new URL("http://www.example.com");
+ ok(url, "URL created");
+
+ var status = false;
+ try {
+ url.href = "42";
+ } catch (e) {
+ status = true;
+ }
+ ok(status, "url.href = 42 should throw");
+
+ url.href = "http://www.example.org";
+ ok(true, "url.href should not throw");
+
+ status = false;
+ try {
+ new URL("42");
+ } catch (e) {
+ status = true;
+ }
+ ok(status, "new URL(42) should throw");
+
+ status = false;
+ try {
+ new URL("http://www.example.com", "42");
+ } catch (e) {
+ status = true;
+ }
+ ok(status, "new URL(something, 42) should throw");
+
+ postMessage({ type: "finish" });
+};
diff --git a/dom/url/tests/url_worker.js b/dom/url/tests/url_worker.js
new file mode 100644
index 0000000000..8a69744603
--- /dev/null
+++ b/dom/url/tests/url_worker.js
@@ -0,0 +1,98 @@
+/* eslint-env worker */
+
+onmessage = function (event) {
+ if (event.data != 0) {
+ var worker = new Worker("url_worker.js");
+ worker.onmessage = function (ev) {
+ postMessage(ev.data);
+ };
+
+ worker.postMessage(event.data - 1);
+ return;
+ }
+
+ let status = false;
+ try {
+ if (URL instanceof Object) {
+ status = true;
+ }
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "URL object:" + URL });
+
+ status = false;
+ var blob = null;
+ try {
+ blob = new Blob([]);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob:" + blob });
+
+ status = false;
+ let url = null;
+ try {
+ url = URL.createObjectURL(blob);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob URL:" + url });
+
+ status = false;
+ try {
+ URL.revokeObjectURL(url);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob Revoke URL" });
+
+ status = false;
+ url = null;
+ try {
+ url = URL.createObjectURL(true);
+ } catch (e) {
+ status = true;
+ }
+
+ postMessage({
+ type: "status",
+ status,
+ msg: "CreateObjectURL should fail if the arg is not a blob",
+ });
+
+ status = false;
+ url = null;
+ try {
+ url = URL.createObjectURL(blob);
+ status = true;
+ } catch (e) {}
+
+ postMessage({ type: "status", status, msg: "Blob URL2:" + url });
+ postMessage({ type: "url", url });
+
+ status = false;
+ try {
+ URL.createObjectURL({});
+ } catch (e) {
+ status = true;
+ }
+
+ postMessage({ type: "status", status, msg: "Exception wanted" });
+
+ blob = new Blob([123]);
+ var uri = URL.createObjectURL(blob);
+ postMessage({
+ type: "status",
+ status: !!uri,
+ msg: "The URI has been generated from the blob",
+ });
+
+ var u = new URL(uri);
+ postMessage({
+ type: "status",
+ status: u.origin == location.origin,
+ msg: "The URL generated from a blob URI has an origin.",
+ });
+
+ postMessage({ type: "finish" });
+};