Skip to content

Commit aad71a6

Browse files
Bug 1862325 [wpt PR 42873] - NavigationActivation prototype, a=testonly
Automatic update from web-platform-tests NavigationActivation prototype (#42873) NavigationActivation is a new object (exposed as `navigation.activation`). It is updated when a new Document is "activated": initial Document creation, restore from bfcache, or (in a future CL) prerender activation. It has three pieces of state: * `activation.entry`: The current NavigationHistoryEntry at the time of activation. * `activation.from`: The current NavigationHistoryEntry immediately before activation (i.e., the entry we came from). This will be null if the navigation was cross-origin, or if the previous entry was not in the same-origin contiguous region of the back/forward list that is available in `navigation.entries()`. * `activation.navigationType`: The navigationType ('push', 'replace', 'reload', or 'traverse') of the navigation that activated the current Document. Note that `entry` or `from` may be a NavigationHistoryEntry that is no longer present in `navigation.entries()` (e.g., when doing a replace navigation, `activation.from` will be the replaced entry). In that case, the entry will remain visible, but because it is a "disposed" entry, its index will be -1 and attempting to `navigation.traverseTo()` its key will be rejected. Initial discussion: whatwg/html#9760 Draft spec PR: whatwg/html#9856 I2p: https://groups.google.com/a/chromium.org/g/blink-dev/c/EfqxeH3Iwh4 Bug: 1492932 Change-Id: I2e090a8366906e4cb6778893ad9ffdca18d6ec37 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4990011 Reviewed-by: Domenic Denicola <[email protected]> Commit-Queue: Nate Chapin <[email protected]> Cr-Commit-Position: refs/heads/main@{#1220983} Co-authored-by: Nate Chapin <[email protected]> -- wpt-commits: c2ca6ebdc7f92fbaf7308c91dda05bcaf24ef455 wpt-pr: 42873
1 parent 738c02b commit aad71a6

17 files changed

+415
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script src="/common/utils.js"></script>
5+
<script src="/common/dispatcher/dispatcher.js"></script>
6+
<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
7+
<script src="resources/is_uuid.js"></script>
8+
9+
<script>
10+
// This test ensures that navigation.activation is properly updated when a page
11+
// is restored from bfcache.
12+
runBfcacheTest({
13+
targetOrigin: originSameSite,
14+
async funcAfterAssertion(pageA, pageB) {
15+
const activationData = await pageA.execute_script(() => {
16+
return { entryURL : navigation.activation.entry.url,
17+
fromIsNull : navigation.activation.from === null,
18+
navigationType : navigation.activation.navigationType }
19+
});
20+
21+
// activation.entry should be the currently activated page, and
22+
// activation.from should be omitted because it is a different origin.
23+
assert_equals(activationData.entryURL, pageA.url);
24+
assert_true(activationData.fromIsNull);
25+
assert_equals(activationData.navigationType, "traverse");
26+
}
27+
}, "navigation.activation must be updated when restored from bfcache");
28+
</script>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script src="/common/utils.js"></script>
5+
<script src="/common/dispatcher/dispatcher.js"></script>
6+
<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
7+
<script src="resources/is_uuid.js"></script>
8+
9+
<script>
10+
// This test ensures that navigation.activation is properly updated when a page
11+
// is restored from bfcache.
12+
runBfcacheTest({
13+
targetOrigin: originSameOrigin,
14+
async funcAfterAssertion(pageA, pageB) {
15+
const activationData = await pageA.execute_script(() => {
16+
return { entryURL : navigation.activation.entry.url,
17+
fromURL : navigation.activation.from.url,
18+
navigationType : navigation.activation.navigationType }
19+
});
20+
21+
// activation.entry should be the currently activated page, and
22+
// activation.from should be the page before restored from bfcache.
23+
assert_equals(activationData.entryURL, pageA.url);
24+
assert_equals(activationData.fromURL, pageB.url);
25+
assert_equals(activationData.navigationType, "traverse");
26+
27+
const entryAndCurrentMatch = await pageA.execute_script(() => navigation.activation.entry === navigation.currentEntry);
28+
assert_true(entryAndCurrentMatch);
29+
30+
const fromAndEntriesArrayMatch = await pageA.execute_script(() => navigation.activation.from === navigation.entries()[navigation.currentEntry.index + 1]);
31+
assert_true(fromAndEntriesArrayMatch);
32+
}
33+
}, "navigation.activation must be updated when restored from bfcache");
34+
</script>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script>
5+
promise_test(async t => {
6+
// Wait for after the load event so that the navigation doesn't get converted
7+
// into a replace navigation.
8+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
9+
10+
assert_equals(navigation.activation.entry, navigation.currentEntry);
11+
let activationEntry = navigation.activation.entry;
12+
let entryIndexBeforePush = activationEntry.index;
13+
history.pushState("#fragment", "", "");
14+
assert_not_equals(navigation.activation.entry, navigation.currentEntry);
15+
assert_equals(navigation.activation.entry, activationEntry);
16+
assert_equals(navigation.activation.entry.index, entryIndexBeforePush);
17+
}, "navigation.activation.entry should not change due to history.pushState()");
18+
</script>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script>
5+
promise_test(async t => {
6+
// Wait for after the load event so that the navigation doesn't get converted
7+
// into a replace navigation.
8+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
9+
10+
assert_equals(navigation.activation.entry, navigation.currentEntry);
11+
let activationEntry = navigation.activation.entry;
12+
history.replaceState("#fragment", "", "");
13+
assert_not_equals(navigation.activation.entry, navigation.currentEntry);
14+
assert_equals(navigation.activation.entry, activationEntry);
15+
assert_equals(navigation.activation.entry.index, -1);
16+
}, "navigation.activation.entry should be orphaned by history.replaceState()");
17+
</script>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<iframe id="i"></iframe>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
assert_equals(i.contentWindow.navigation.activation, null);
12+
13+
i.contentWindow.navigation.navigate("/common/blank.html?a");
14+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
15+
16+
assert_equals(i.contentWindow.navigation.entries().length, 1);
17+
assert_equals(i.contentWindow.navigation.activation.entry,
18+
i.contentWindow.navigation.currentEntry);
19+
assert_equals(i.contentWindow.navigation.activation.from.url, "about:blank");
20+
assert_equals(i.contentWindow.navigation.activation.from.index, -1);
21+
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
22+
}, "navigation.activation interaction with initial about:blank");
23+
</script>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script src="/common/get-host-info.sub.js"></script>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
let i = document.createElement("iframe");
12+
i.src = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + "/common/blank.html";
13+
document.body.appendChild(i);
14+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
15+
16+
i.contentWindow.location = "/common/blank.html";
17+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
18+
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;
19+
20+
assert_equals(i.contentWindow.navigation.entries().length, 1);
21+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
22+
assert_equals(i.contentWindow.navigation.activation.from, null);
23+
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
24+
}, "navigation.activation after push cross-origin");
25+
</script>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<iframe id="i" src="/common/blank.html"></iframe>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
i.contentWindow.navigation.navigate("/common/blank.html?a");
12+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
13+
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;
14+
15+
assert_equals(i.contentWindow.navigation.entries().length, 2);
16+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
17+
assert_equals(i.contentWindow.navigation.activation.from,
18+
i.contentWindow.navigation.entries()[0]);
19+
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
20+
21+
// Same-document navigation doesn't change navigation.activation.
22+
await i.contentWindow.navigation.navigate("/common/blank.html?a#fragment").finished;
23+
24+
assert_equals(i.contentWindow.navigation.entries().length, 3);
25+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
26+
assert_equals(i.contentWindow.navigation.activation.from,
27+
i.contentWindow.navigation.entries()[0]);
28+
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
29+
}, "navigation.activation after push");
30+
</script>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<iframe id="i" src="/common/blank.html"></iframe>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
i.contentWindow.navigation.reload();
12+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
13+
14+
// activation.entry and activation.from are equal after reload
15+
assert_equals(i.contentWindow.navigation.entries().length, 1);
16+
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
17+
assert_equals(i.contentWindow.navigation.activation.entry,
18+
i.contentWindow.navigation.activation.from);
19+
assert_equals(i.contentWindow.navigation.activation.navigationType, "reload");
20+
}, "navigation.activation after reload");
21+
</script>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<script src="/common/get-host-info.sub.js"></script>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
let i = document.createElement("iframe");
12+
i.src = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + "/common/blank.html";
13+
document.body.appendChild(i);
14+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
15+
16+
i.contentWindow.location.replace("/common/blank.html");
17+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
18+
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;
19+
20+
assert_equals(i.contentWindow.navigation.entries().length, 1);
21+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
22+
assert_equals(i.contentWindow.navigation.activation.from, null);
23+
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
24+
}, "navigation.activation after replace cross-origin");
25+
</script>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!doctype html>
2+
<script src="/resources/testharness.js"></script>
3+
<script src="/resources/testharnessreport.js"></script>
4+
<iframe id="i" src="/common/blank.html"></iframe>
5+
<script>
6+
promise_test(async t => {
7+
// Wait for after the load event so that the navigation doesn't get converted
8+
// into a replace navigation.
9+
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
10+
11+
let before_key = i.contentWindow.navigation.currentEntry.key;
12+
let before_id = i.contentWindow.navigation.currentEntry.id;
13+
let before_url = i.contentWindow.navigation.currentEntry.url;
14+
i.contentWindow.navigation.navigate("/common/blank.html?a", { history: "replace" });
15+
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
16+
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;
17+
let from_entry_after_nav = i.contentWindow.navigation.activation.from;
18+
19+
// activation.entry is the current entry. activation.from is a new
20+
// NavigationHistoryEntry object (because there is a new window), with the
21+
// same key/id/url as before the navigation, and an index of -1 because it is
22+
// not present in the entries array.
23+
assert_equals(i.contentWindow.navigation.entries().length, 1);
24+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
25+
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
26+
assert_equals(from_entry_after_nav.key, before_key);
27+
assert_equals(from_entry_after_nav.id, before_id);
28+
assert_equals(from_entry_after_nav.url, before_url);
29+
assert_equals(from_entry_after_nav.index, -1);
30+
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
31+
32+
await i.contentWindow.navigation.navigate("/common/blank.html?a#fragment", { history: "replace" }).finished;
33+
34+
// activation.entry is no longer navigation.currentEntry and is disposed.
35+
// activation.from has not changed.
36+
assert_equals(i.contentWindow.navigation.entries().length, 1);
37+
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
38+
assert_not_equals(i.contentWindow.navigation.activation.entry,
39+
i.contentWindow.navigation.currentEntry);
40+
assert_equals(i.contentWindow.navigation.activation.entry.index, -1);
41+
assert_equals(i.contentWindow.navigation.activation.from, from_entry_after_nav);
42+
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
43+
}, "navigation.activation after replace");
44+
</script>

0 commit comments

Comments
 (0)