diff --git a/dom/nodes/Document-base-url-not-live.window.js b/dom/nodes/Document-base-url-not-live.window.js
new file mode 100644
index 00000000000000..f2d19882d75bc4
--- /dev/null
+++ b/dom/nodes/Document-base-url-not-live.window.js
@@ -0,0 +1,54 @@
+// Confirms that the base URL an about:blank or about:srcdoc document inherits
+// from its initiator/container is a snapshot taken at creation, not a live view
+// of the initiator's current base URL.
+//
+// Reading baseURI is not enough on its own: implementations cache the base URL,
+// so a live-but-cached implementation would still return the creation-time value
+// on read. To distinguish snapshot from live, the container's base URL is changed
+// and the child is then forced to recompute its base URL (by inserting and
+// removing a ). A snapshot yields the creation-time value; a live view
+// yields the container's new base URL.
+//
+// See https://github.com/whatwg/dom/issues/454
+
+function makeIframe(doc, configure) {
+ return new Promise(resolve => {
+ const iframe = doc.createElement("iframe");
+ configure(iframe);
+ iframe.addEventListener("load", () => resolve(iframe), { once: true });
+ doc.body.appendChild(iframe);
+ });
+}
+
+// Inserting then removing a makes the document recompute its base URL.
+function forceBaseURLRecompute(doc) {
+ const base = doc.createElement("base");
+ base.setAttribute("href", "http://example.org/forced/");
+ doc.head.appendChild(base);
+ doc.head.removeChild(base);
+}
+
+function notLiveTest(configureChild) {
+ return async t => {
+ const container = await makeIframe(document, f => f.src = "about:blank");
+ t.add_cleanup(() => container.remove());
+ const cdoc = container.contentDocument;
+
+ const child = await makeIframe(cdoc, configureChild);
+ const childDoc = child.contentDocument;
+ const inherited = childDoc.baseURI;
+
+ const cbase = cdoc.createElement("base");
+ cbase.setAttribute("href", "http://example.com/changed/");
+ cdoc.head.appendChild(cbase);
+ assert_equals(cdoc.baseURI, "http://example.com/changed/", "container base URL changed");
+
+ forceBaseURLRecompute(childDoc);
+ assert_equals(childDoc.baseURI, inherited,
+ "child base URL is a snapshot from creation, not the container's current base URL");
+ };
+}
+
+promise_test(notLiveTest(f => f.src = "about:blank"), "about:blank base URL is not live");
+
+promise_test(notLiveTest(f => f.srcdoc = "x"), "about:srcdoc base URL is not live");
diff --git a/dom/nodes/Document-cloneNode-about-base-url-relative.window.js b/dom/nodes/Document-cloneNode-about-base-url-relative.window.js
new file mode 100644
index 00000000000000..deadfd9f2ffbbf
--- /dev/null
+++ b/dom/nodes/Document-cloneNode-about-base-url-relative.window.js
@@ -0,0 +1,40 @@
+// A relative href in an about:blank document, and how it interacts with
+// cloning.
+//
+// The base URL an about:blank document inherits from its initiator is exposed
+// through the no- path (base URL override), so ordinary relative URLs
+// resolve against it. A element, however, resolves its href against the
+// document's own URL, so a relative resolves against
+// about:blank rather than the inherited base URL. Cloning does not change this.
+//
+// See https://github.com/whatwg/dom/issues/454
+
+function aboutBlankDocument(t) {
+ return new Promise(resolve => {
+ const iframe = document.createElement("iframe");
+ iframe.src = "about:blank";
+ iframe.onload = () => resolve(iframe);
+ t.add_cleanup(() => iframe.remove());
+ document.body.appendChild(iframe);
+ });
+}
+
+promise_test(async t => {
+ const doc = (await aboutBlankDocument(t)).contentDocument;
+
+ const base = doc.createElement("base");
+ base.setAttribute("href", "sub/");
+ doc.head.appendChild(base);
+ assert_equals(doc.baseURI, "about:blank");
+}, "A relative in an about:blank document resolves against about:blank");
+
+promise_test(async t => {
+ const doc = (await aboutBlankDocument(t)).contentDocument;
+
+ const base = doc.createElement("base");
+ base.setAttribute("href", "sub/");
+ doc.head.appendChild(base);
+
+ assert_equals(doc.cloneNode(true).baseURI, "about:blank", "deep");
+ assert_equals(doc.cloneNode(false).baseURI, "about:blank", "shallow");
+}, "Clone of an about:blank document with a relative ");
diff --git a/dom/nodes/Document-cloneNode-srcdoc-base-url.window.js b/dom/nodes/Document-cloneNode-srcdoc-base-url.window.js
new file mode 100644
index 00000000000000..4a78497631a2d3
--- /dev/null
+++ b/dom/nodes/Document-cloneNode-srcdoc-base-url.window.js
@@ -0,0 +1,32 @@
+// A relative href in an about:srcdoc document, and how it interacts with
+// cloning. Parallels the about:blank case.
+//
+// The base URL an about:srcdoc document inherits from its container is exposed
+// through the no- path (base URL override), so ordinary relative URLs
+// resolve against it. A element, however, resolves its href against the
+// document's own URL, so a relative resolves against
+// about:srcdoc rather than the inherited base URL. Cloning does not change this.
+//
+// See https://github.com/whatwg/dom/issues/454
+
+function srcdocDocument(t, srcdoc) {
+ return new Promise(resolve => {
+ const iframe = document.createElement("iframe");
+ iframe.srcdoc = srcdoc;
+ iframe.onload = () => resolve(iframe);
+ t.add_cleanup(() => iframe.remove());
+ document.body.appendChild(iframe);
+ });
+}
+
+promise_test(async t => {
+ const doc = (await srcdocDocument(t, "x")).contentDocument;
+ assert_equals(doc.baseURI, "about:srcdoc");
+}, "A relative in an about:srcdoc document resolves against about:srcdoc");
+
+promise_test(async t => {
+ const doc = (await srcdocDocument(t, "x")).contentDocument;
+
+ assert_equals(doc.cloneNode(true).baseURI, "about:srcdoc", "deep");
+ assert_equals(doc.cloneNode(false).baseURI, "about:srcdoc", "shallow");
+}, "Clone of an about:srcdoc document with a relative ");