Skip to content

Commit 0bd0091

Browse files
hiroshige-gmoz-wptsync-bot
authored andcommitted
Bug 1733861 [wpt PR 31083] - [WPT] BFCache: pushState() in BFCache/non-BFCache cases, a=testonly
Automatic update from web-platform-tests [WPT] BFCache: pushState() in BFCache/non-BFCache cases When doing history navigation to an entry that's created via pushState, the page should be: - With BFCache: Restored from BFCache. - Without BFCache: Loaded from the URL set by `pushState()`. While this test contradicts the current spec but matches the desired behavior, and the spec will be fixed as part of whatwg/html#6315. Tests pass on Firefox/Safari/Chrome, except for Safari on non-BFCache case (just because WebLock doesn't disable BFCache). Bug: 1107415, 1298336, whatwg/html#6207 Change-Id: I609276fe865fa92409fd7a547777dba222bac36c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3199857 Reviewed-by: Kouhei Ueno <[email protected]> Reviewed-by: Domenic Denicola <[email protected]> Reviewed-by: Rakina Zata Amni <[email protected]> Commit-Queue: Hiroshige Hayashizaki <[email protected]> Cr-Commit-Position: refs/heads/main@{#972799} -- wpt-commits: a400637a6ee3b7b6f315be2a17a7b28257663b4b wpt-pr: 31083
1 parent c7075e0 commit 0bd0091

File tree

4 files changed

+141
-49
lines changed

4 files changed

+141
-49
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!DOCTYPE HTML>
2+
<meta name="timeout" content="long">
3+
<script src="/resources/testharness.js"></script>
4+
<script src="/resources/testharnessreport.js"></script>
5+
<script src="/common/utils.js"></script>
6+
<script src="/common/dispatcher/dispatcher.js"></script>
7+
<script src="resources/helper.sub.js"></script>
8+
<script>
9+
// Tests what happens when doing history navigation to an entry that's created
10+
// via pushState, with and without BFCache:
11+
// 1. Navigate to `urlA`.
12+
// 2. `pushState(urlPushState)`.
13+
// 3. Navigate to `urlB`.
14+
// 4. Do a back navigation.
15+
// With BFCache, the page loaded at Step 1 is restored from BFCache,
16+
// and is not reloaded from `urlPushState` nor `urlA`.
17+
// Without BFCache, a page is loaded from `urlPushState`, not from `urlA`.
18+
// In both cases, `location` and `history.state` are set to those set by
19+
// `pushState()` in Step 2.
20+
// See https://github.com/whatwg/html/issues/6207 for more discussion on the
21+
// specified, implemented and desired behaviors. While this test contradicts
22+
// the current spec but matches the desired behavior, and the spec will be
23+
// fixed as part of https://github.com/whatwg/html/pull/6315.
24+
for (const bfcacheDisabled of [false, true]) {
25+
const pushStateExecutorPath =
26+
'/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html';
27+
28+
runBfcacheTest({
29+
funcBeforeNavigation: async (bfcacheDisabled, pushStateExecutorPath) => {
30+
const urlPushState = new URL(location.href);
31+
urlPushState.pathname = pushStateExecutorPath;
32+
if (bfcacheDisabled) {
33+
await disableBFCache();
34+
}
35+
36+
// `pushState(..., urlPushState)` on `urlA`,
37+
history.pushState('blue', '', urlPushState.href);
38+
},
39+
argsBeforeNavigation: [bfcacheDisabled, pushStateExecutorPath],
40+
shouldBeCached: !bfcacheDisabled,
41+
funcAfterAssertion: async (pageA) => {
42+
// We've navigated to `urlB` and back again
43+
// (already done within `runBfcacheTest()`).
44+
// After the back navigation, `location` etc. should point to
45+
// `urlPushState` and the state that's pushed.
46+
const urlPushState = location.origin + pushStateExecutorPath +
47+
'?uuid=' + pageA.context_id;
48+
assert_equals(await pageA.execute_script(() => location.href),
49+
urlPushState, 'url');
50+
assert_equals(await pageA.execute_script(() => history.state),
51+
'blue', 'history.state');
52+
53+
if (bfcacheDisabled) {
54+
// When the page is not restored from BFCache, the HTML page is loaded
55+
// from `urlPushState` (not from `urlA`).
56+
assert_true(await pageA.execute_script(() => isLoadedFromPushState),
57+
'document should be loaded from urlPushState');
58+
}
59+
}
60+
}, 'back navigation to pushState()d page (' +
61+
(bfcacheDisabled ? 'not ' : '') + 'in BFCache)');
62+
}
63+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE HTML>
2+
<script src="/common/dispatcher/dispatcher.js"></script>
3+
<script src="event-recorder.js" type="module"></script>
4+
<script src="worker-helper.js" type="module"></script>
5+
<script type="module">
6+
// This is mostly the same as `executor.html`, except for
7+
// `isLoadedFromPushState` is set here, in order to detect whether the page
8+
// was loaded from `executor.html` or `executor-pushstate.html`.
9+
// Full executor functionality is still needed to handle remote script
10+
// execution requests etc.
11+
window.isLoadedFromPushState = true;
12+
</script>
13+
<script src="executor.js" type="module"></script>

testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,4 @@
22
<script src="/common/dispatcher/dispatcher.js"></script>
33
<script src="event-recorder.js" type="module"></script>
44
<script src="worker-helper.js" type="module"></script>
5-
<script type="module">
6-
const params = new URLSearchParams(window.location.search);
7-
const uuid = params.get('uuid');
8-
9-
// Executor and BFCache detection
10-
11-
// When navigating out from this page, always call
12-
// `prepareNavigation(callback)` synchronously from the script injected by
13-
// `RemoteContext.execute_script()`, and trigger navigation on or after the
14-
// callback is called.
15-
// prepareNavigation() suspends task polling and avoid in-flight fetch
16-
// requests during navigation that might evict the page from BFCache.
17-
//
18-
// When we navigate to the page again, task polling is resumed, either
19-
// - (BFCache cases) when the pageshow event listener added by
20-
// prepareNavigation() is executed, or
21-
// - (Non-BFCache cases) when `Executor.execute()` is called again during
22-
// non-BFCache page loading.
23-
//
24-
// In such scenarios, `assert_bfcached()` etc. in `helper.sub.js` can determine
25-
// whether the page is restored from BFCache or not, by observing
26-
// - `isPageshowFired`: whether the pageshow event listener added by the
27-
// prepareNavigation() before navigating out, and
28-
// - `loadCount`: whether this inline script is evaluated again.
29-
// - `isPageshowPersisted` is used to assert that `event.persisted` is true
30-
// when restored from BFCache.
31-
32-
window.isPageshowFired = false;
33-
window.isPageshowPersisted = null;
34-
window.loadCount = parseInt(localStorage.getItem(uuid + '.loadCount') || '0') + 1;
35-
localStorage.setItem(uuid + '.loadCount', loadCount);
36-
37-
window.pageShowPromise = new Promise(resolve =>
38-
window.addEventListener('pageshow', resolve, {once: true}));
39-
40-
const executor = new Executor(uuid);
41-
42-
window.prepareNavigation = function(callback) {
43-
window.addEventListener(
44-
'pageshow',
45-
(event) => {
46-
window.isPageshowFired = true;
47-
window.isPageshowPersisted = event.persisted;
48-
executor.resume();
49-
},
50-
{once: true});
51-
executor.suspend(callback);
52-
}
53-
</script>
5+
<script src="executor.js" type="module"></script>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const params = new URLSearchParams(window.location.search);
2+
const uuid = params.get('uuid');
3+
4+
// Executor and BFCache detection
5+
6+
// When navigating out from this page, always call
7+
// `prepareNavigation(callback)` synchronously from the script injected by
8+
// `RemoteContext.execute_script()`, and trigger navigation on or after the
9+
// callback is called.
10+
// prepareNavigation() suspends task polling and avoid in-flight fetch
11+
// requests during navigation that might evict the page from BFCache.
12+
//
13+
// When we navigate to the page again, task polling is resumed, either
14+
// - (BFCache cases) when the pageshow event listener added by
15+
// prepareNavigation() is executed, or
16+
// - (Non-BFCache cases) when `Executor.execute()` is called again during
17+
// non-BFCache page loading.
18+
//
19+
// In such scenarios, `assert_bfcached()` etc. in `helper.sub.js` can determine
20+
// whether the page is restored from BFCache or not, by observing
21+
// - `isPageshowFired`: whether the pageshow event listener added by the
22+
// prepareNavigation() before navigating out, and
23+
// - `loadCount`: whether this inline script is evaluated again.
24+
// - `isPageshowPersisted` is used to assert that `event.persisted` is true
25+
// when restored from BFCache.
26+
27+
window.isPageshowFired = false;
28+
window.isPageshowPersisted = null;
29+
window.loadCount = parseInt(localStorage.getItem(uuid + '.loadCount') || '0') + 1;
30+
localStorage.setItem(uuid + '.loadCount', loadCount);
31+
32+
window.pageShowPromise = new Promise(resolve =>
33+
window.addEventListener('pageshow', resolve, {once: true}));
34+
35+
const executor = new Executor(uuid);
36+
37+
window.prepareNavigation = function(callback) {
38+
window.addEventListener(
39+
'pageshow',
40+
(event) => {
41+
window.isPageshowFired = true;
42+
window.isPageshowPersisted = event.persisted;
43+
executor.resume();
44+
},
45+
{once: true});
46+
executor.suspend(callback);
47+
}
48+
49+
// Try to disable BFCache by acquiring and never releasing a Web Lock.
50+
// This requires HTTPS.
51+
// Note: This is a workaround depending on non-specified WebLock+BFCache
52+
// behavior, and doesn't work on Safari. We might want to introduce a
53+
// test-only BFCache-disabling API instead in the future.
54+
// https://github.com/web-platform-tests/wpt/issues/16359#issuecomment-795004780
55+
// https://crbug.com/1298336
56+
window.disableBFCache = () => {
57+
return new Promise(resolve => {
58+
// Use page's UUID as a unique lock name.
59+
navigator.locks.request(uuid, () => {
60+
resolve();
61+
return new Promise(() => {});
62+
});
63+
});
64+
};

0 commit comments

Comments
 (0)