Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make popstate always fire synchronously #33746

Merged
merged 1 commit into from Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

// 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement.
window.addEventListener("load", () => t.step_timeout(() => {
assert_array_equals(window.eventOrder, ["load"]);

window.addEventListener("hashchange", t.step_func(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "popstate", "hashchange"]);

window.addEventListener("hashchange", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "popstate", "hashchange", "hashchange"]);
}));
}), { once: true });

location.hash = "#1";
assert_array_equals(window.eventOrder, ["load", "popstate"]);
location.hash = "#2";
assert_array_equals(window.eventOrder, ["load", "popstate", "popstate"]);
}, 0));
}, "when changing hash, after the load event");
</script>
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

// 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement.
window.addEventListener("load", () => t.step_timeout(() => {
assert_array_equals(window.eventOrder, ["load"]);

window.addEventListener("hashchange", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]);
}));

location.hash = "#1";
assert_array_equals(window.eventOrder, ["load", "popstate"]);
}, 0));
}, "when changing hash, after the load event");
</script>
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

// 0 timeout is necessary because if we do pushState before load is finished firing it counts as a replacement.
window.addEventListener("load", () => t.step_timeout(() => {
assert_array_equals(window.eventOrder, ["load"]);

t.step_timeout(t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load"]);
}), 100);

history.pushState({ state: "new state" }, "");
}, 0));
}, "when pushing state, after the load event");
</script>
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

window.addEventListener("load", t.step_func(() => {
assert_array_equals(window.eventOrder, ["load"]);

t.step_timeout(t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load"]);
}), 100);

history.replaceState({ state: "new state" }, "");
}));
}, "when replacing state, after the load event");
</script>
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

window.addEventListener("load", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["popstate", "popstate", "hashchange", "hashchange", "load"]);
}));

location.hash = "#1";
assert_array_equals(window.eventOrder, ["popstate"]);
location.hash = "#2";
assert_array_equals(window.eventOrder, ["popstate", "popstate"]);
}, "when changing hash twice, before load");
</script>
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

window.addEventListener("load", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["popstate", "hashchange", "load"]);
}));

location.hash = "#1";
assert_array_equals(window.eventOrder, ["popstate"]);
}, "when changing hash, before load");
</script>
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

window.addEventListener("load", t.step_func(() => {
t.step_timeout(t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load"]);
}), 100);
}));

history.pushState({ state: "new state" }, "");
}, "when pushing state, before load");
</script>
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

t.step_timeout(t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load"]);
}), 100);

history.replaceState({ state: "new state" }, "");
}, "when replacing state, before load");
</script>
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(t => {
let popstate_called = false;
window.onpopstate = t.step_func(e => {
popstate_called = true;
history.pushState(2, null, "#2");
assert_not_equals(history.state, e.state);
});
location.hash = "#1";
assert_true(popstate_called);
}, "pushState inside popstate")
</script>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

// 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement.
window.addEventListener("load", () => t.step_timeout(() => {
assert_array_equals(window.eventOrder, ["load"]);

window.addEventListener("hashchange", t.step_func(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]);

window.addEventListener("hashchange", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange", "popstate", "hashchange"]);
}));
}), { once: true });

location.hash = "#1";
assert_array_equals(window.eventOrder, ["load", "popstate"]);
history.back();
assert_array_equals(window.eventOrder, ["load", "popstate"]);
}, 0));
}, "when traversing back, before hashchange");
</script>
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Popstate/hashchange/load event ordering</title>

<script>
// Set these up super-early before we hit the network for the test harness, just in case.
window.eventOrder = [];
window.onhashchange = () => window.eventOrder.push("hashchange");
window.onpopstate = () => window.eventOrder.push("popstate");
window.onload = () => window.eventOrder.push("load");
</script>

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<script>
async_test(t => {
assert_array_equals(window.eventOrder, []);

// 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement.
window.addEventListener("load", () => t.step_timeout(() => {
assert_array_equals(window.eventOrder, ["load"]);

window.addEventListener("hashchange", t.step_func(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]);

window.addEventListener("hashchange", t.step_func_done(() => {
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange", "popstate", "hashchange"]);
}));

history.back();
assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]);
}), { once: true });

location.hash = "#1";
assert_array_equals(window.eventOrder, ["load", "popstate"]);
}, 0));
}, "when traversing back, after hashchange");
</script>