tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

same-hash.html (4449B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Using the location interface to navigate to the same hash as the current one</title>
      4 <link rel="help" href="https://github.com/whatwg/html/issues/7386">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 
      8 <iframe id="i" srcdoc="<div style='height: 200vh'></div><div id='te&lt;st'></div>"></iframe>
      9 
     10 <script type="module">
     11 setup({ explicit_done: true });
     12 await new Promise(r => window.onload = r);
     13 
     14 for (const value of ["#te<st", "te<st", "#te%3Cst", "te%3Cst"]) {
     15  promise_test(async t => {
     16    t.add_cleanup(() => { i.contentWindow.location.hash = ""; });
     17    assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top");
     18 
     19    i.contentWindow.location.hash = "te<st";
     20    await delayForFragmentNavigationScrolling(t);
     21 
     22    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe");
     23 
     24    i.contentWindow.scroll({ top: 0, behavior: "instant" });
     25    assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work");
     26 
     27    i.contentWindow.location.hash = value;
     28    await delayForFragmentNavigationScrolling(t);
     29 
     30    assert_equals(i.contentWindow.scrollY, 0, "Reassigning the same hash must not change the scroll position");
     31  }, `Using location.hash = "${value}" must not reset scroll position`);
     32 }
     33 
     34 // These don't canonicalize to the current value of location.hash; the post-parsing version of
     35 // "te<st" is "te%3Cst", uppercase.
     36 for (const value of ["#te%3cst", "te%3cst"]) {
     37  promise_test(async t => {
     38    t.add_cleanup(() => { i.contentWindow.location.hash = ""; });
     39    assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top");
     40 
     41    i.contentWindow.location.hash = "te<st";
     42    await delayForFragmentNavigationScrolling(t);
     43 
     44    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe");
     45 
     46    i.contentWindow.scroll({ top: 0, behavior: "instant" });
     47    assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work");
     48 
     49    i.contentWindow.location.hash = value;
     50    await delayForFragmentNavigationScrolling(t);
     51 
     52    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Reassigning the same-ish hash scrolls the iframe");
     53  }, `Using location.hash = "${value}" must reset scroll position`);
     54 }
     55 
     56 for (const value of ["about:srcdoc#te<st", "about:srcdoc#te%3cst", "about:srcdoc#te%3Cst"]) {
     57  promise_test(async t => {
     58    t.add_cleanup(() => { i.contentWindow.location.hash = ""; });
     59    assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top");
     60 
     61    i.contentWindow.location.hash = "te<st";
     62    await delayForFragmentNavigationScrolling(t);
     63 
     64    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe");
     65 
     66    i.contentWindow.scroll({ top: 0, behavior: "instant" });
     67    assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work");
     68 
     69    i.contentWindow.location.href = value;
     70    await delayForFragmentNavigationScrolling(t);
     71 
     72    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe");
     73  }, `Using location.href = "${value}" must reset scroll position`);
     74 
     75  promise_test(async t => {
     76    t.add_cleanup(() => { i.contentWindow.location.hash = ""; });
     77    assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top");
     78 
     79    i.contentWindow.location.hash = "te<st";
     80    await delayForFragmentNavigationScrolling(t);
     81 
     82    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe");
     83 
     84    i.contentWindow.scroll({ top: 0, behavior: "instant" });
     85    assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work");
     86 
     87    i.contentWindow.location.assign(value);
     88    await delayForFragmentNavigationScrolling(t);
     89 
     90    assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe");
     91  }, `Using location.assign("${value}") must reset scroll position`);
     92 }
     93 
     94 function delayForFragmentNavigationScrolling(t) {
     95  // Scroll behavior for fragment navigation is set to "auto" in the spec, so we can't guarantee it's instant.
     96  // In practice 10 milliseconds seems to be enough.
     97  return new Promise(r => t.step_timeout(r, 10));
     98 }
     99 
    100 done();
    101 </script>