Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions dom/nodes/Document-base-url-not-live.window.js
Original file line number Diff line number Diff line change
@@ -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 <base>). 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 <base> 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");
40 changes: 40 additions & 0 deletions dom/nodes/Document-cloneNode-about-base-url-relative.window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// A relative <base> 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-<base> path (base URL override), so ordinary relative URLs
// resolve against it. A <base> element, however, resolves its href against the
// document's own URL, so a relative <base href="sub/"> 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 <base> 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 <base>");
32 changes: 32 additions & 0 deletions dom/nodes/Document-cloneNode-srcdoc-base-url.window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// A relative <base> 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-<base> path (base URL override), so ordinary relative URLs
// resolve against it. A <base> element, however, resolves its href against the
// document's own URL, so a relative <base href="sub/"> 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, "<base href='sub/'>x")).contentDocument;
assert_equals(doc.baseURI, "about:srcdoc");
}, "A relative <base> in an about:srcdoc document resolves against about:srcdoc");

promise_test(async t => {
const doc = (await srcdocDocument(t, "<base href='sub/'>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 <base>");
Loading