cross-document-traversal-cross-document-traversal.html (6429B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Cross-document traversals during cross-document traversals</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 7 <!-- 8 In the spec, all traversals are queued, and that includes computing what 9 "back" and "forward" mean, based on the "current session history step". The 10 "current session history step" is updated at the end of "apply the history 11 step", at which point the queued steps in "traverse history by a delta" get to 12 run and compute what is back/forward. So the basic structure is: 13 14 - back(), back(): go back once, then again. 15 - back(), forward(): go back once, then go forward. 16 17 However, note that these observable effects (e.g., actually loading an 18 intermediate document) are done via queued tasks. Those tasks will end up not 19 running, once we switch the active document due to the second traversal. So 20 the end observable result looks like: 21 22 - back(), back(): go back -2. 23 - back(), forward(): go nowhere. 24 --> 25 26 <body> 27 <script type="module"> 28 import { createIframe, waitForLoad, delay, waitForPotentialNetworkLoads } from "./resources/helpers.mjs"; 29 30 promise_test(async t => { 31 const iframe = await createIframe(t); 32 33 // Setup 34 // Extra delay()s are necessary because if we navigate "inside" the load 35 // handler (i.e. in a promise reaction for the load handler) then it will 36 // be a replace navigation. 37 iframe.contentWindow.location.search = "?1"; 38 await waitForLoad(iframe); 39 await delay(t, 0); 40 iframe.contentWindow.location.search = "?2"; 41 await waitForLoad(iframe); 42 await delay(t, 0); 43 iframe.contentWindow.location.search = "?3"; 44 await waitForLoad(iframe); 45 await delay(t, 0); 46 iframe.contentWindow.history.back(); 47 await waitForLoad(iframe); 48 await delay(t, 0); 49 assert_equals(iframe.contentWindow.location.search, "?2", "we made our way to ?2 for setup"); 50 51 iframe.contentWindow.history.back(); 52 assert_equals(iframe.contentWindow.location.search, "?2", "must not go back synchronously"); 53 54 iframe.contentWindow.history.forward(); 55 assert_equals(iframe.contentWindow.location.search, "?2", "must not go forward synchronously"); 56 57 iframe.onload = t.unreached_func("second load event"); 58 59 await waitForPotentialNetworkLoads(t); 60 assert_equals(iframe.contentWindow.location.search, "?2", "must stay on ?2"); 61 }, "cross-document traversals in opposite directions: the result is going nowhere"); 62 63 promise_test(async t => { 64 const iframe = await createIframe(t); 65 66 // Setup 67 // Extra delay()s are necessary because if we navigate "inside" the load 68 // handler (i.e. in a promise reaction for the load handler) then it will 69 // be a replace navigation. 70 iframe.contentWindow.location.search = "?1"; 71 await waitForLoad(iframe); 72 await delay(t, 0); 73 iframe.contentWindow.location.search = "?2"; 74 await waitForLoad(iframe); 75 await delay(t, 0); 76 77 iframe.contentWindow.history.back(); 78 assert_equals(iframe.contentWindow.location.search, "?2", "must not go back synchronously"); 79 80 iframe.contentWindow.history.forward(); 81 assert_equals(iframe.contentWindow.location.search, "?2", "must not go forward synchronously"); 82 83 iframe.onload = t.unreached_func("second load event"); 84 85 await waitForPotentialNetworkLoads(t); 86 assert_equals(iframe.contentWindow.location.search, "?2", "must stay on ?2"); 87 }, "cross-document traversals in opposite directions, second traversal invalid at queuing time but valid at the time it is run: the result is going nowhere"); 88 89 promise_test(async t => { 90 const iframe = await createIframe(t); 91 92 // Setup 93 // Extra delay()s are necessary because if we navigate "inside" the load 94 // handler (i.e. in a promise reaction for the load handler) then it will 95 // be a replace navigation. 96 iframe.contentWindow.location.search = "?1"; 97 await waitForLoad(iframe); 98 await delay(t, 0); 99 iframe.contentWindow.location.search = "?2"; 100 await waitForLoad(iframe); 101 await delay(t, 0); 102 iframe.contentWindow.location.search = "?3"; 103 await waitForLoad(iframe); 104 await delay(t, 0); 105 106 iframe.contentWindow.history.back(); 107 assert_equals(iframe.contentWindow.location.search, "?3", "must not go back synchronously (1)"); 108 109 iframe.contentWindow.history.back(); 110 assert_equals(iframe.contentWindow.location.search, "?3", "must not go back synchronously (2)"); 111 112 await waitForLoad(iframe); 113 assert_equals(iframe.contentWindow.location.search, "?1", "first load event must be going back"); 114 115 iframe.onload = t.unreached_func("second load event"); 116 117 await waitForPotentialNetworkLoads(t); 118 assert_equals(iframe.contentWindow.location.search, "?1", "must stay on ?1"); 119 }, "cross-document traversals in the same (back) direction: the result is going -2 with only one load event"); 120 121 promise_test(async t => { 122 const iframe = await createIframe(t); 123 124 // Setup 125 // Extra delay()s are necessary because if we navigate "inside" the load 126 // handler (i.e. in a promise reaction for the load handler) then it will 127 // be a replace navigation. 128 iframe.contentWindow.location.search = "?1"; 129 await waitForLoad(iframe); 130 await delay(t, 0); 131 iframe.contentWindow.location.search = "?2"; 132 await waitForLoad(iframe); 133 await delay(t, 0); 134 iframe.contentWindow.location.search = "?3"; 135 await waitForLoad(iframe); 136 await delay(t, 0); 137 iframe.contentWindow.history.back(); 138 await waitForLoad(iframe); 139 await delay(t, 0); 140 assert_equals(iframe.contentWindow.location.search, "?2", "we made our way to ?2 for setup"); 141 iframe.contentWindow.history.back(); 142 await waitForLoad(iframe); 143 await delay(t, 0); 144 assert_equals(iframe.contentWindow.location.search, "?1", "we made our way to ?1 for setup"); 145 146 iframe.contentWindow.history.forward(); 147 assert_equals(iframe.contentWindow.location.search, "?1", "must not go forward synchronously (1)"); 148 149 iframe.contentWindow.history.forward(); 150 assert_equals(iframe.contentWindow.location.search, "?1", "must not go forward synchronously (2)"); 151 152 await waitForLoad(iframe); 153 assert_equals(iframe.contentWindow.location.search, "?3", "first load event must be going forward"); 154 155 iframe.onload = t.unreached_func("second load event"); 156 157 await waitForPotentialNetworkLoads(t); 158 assert_equals(iframe.contentWindow.location.search, "?3", "must stay on ?3"); 159 }, "cross-document traversals in the same (forward) direction: the result is going +2 with only one load event"); 160 </script>