tor-browser

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

document-rules-details-element.https.html (3476B)


      1 <!DOCTYPE html>
      2 <title>Speculation rules: no crash with selector_matches and details element</title>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="../resources/utils.js"></script>
      6 
      7 <body>
      8 <script>
      9  setup(() => assertSpeculationRulesIsSupported());
     10 
     11  // This test verifies that using selector_matches with links inside a
     12  // <details> element does not cause a crash. This is a regression test for
     13  // a bug where forcing style computation on links inside a closed <details>
     14  // element would cause DidStyleChildren to incorrectly remove links from
     15  // stale_links_, leading to a DCHECK failure in CSSSelectorPredicate::Matches.
     16  test(() => {
     17    // Create a closed details element with a link inside.
     18    const details = document.createElement('details');
     19    document.body.appendChild(details);
     20 
     21    const summary = document.createElement('summary');
     22    summary.textContent = 'Click to expand';
     23    details.appendChild(summary);
     24 
     25    const link = document.createElement('a');
     26    link.href = 'https://example.com/test';
     27    link.className = 'test-link';
     28    link.textContent = 'Link inside details';
     29    details.appendChild(link);
     30 
     31    // Insert a document rule with selector_matches.
     32    const script = document.createElement('script');
     33    script.type = 'speculationrules';
     34    script.textContent = JSON.stringify({
     35      prefetch: [{
     36        source: 'document',
     37        eagerness: 'immediate',
     38        where: { selector_matches: 'a.test-link' }
     39      }]
     40    });
     41    document.head.appendChild(script);
     42 
     43    // Force style computation on the link. This triggers a forced update
     44    // which temporarily allows style computation on display-locked elements.
     45    // Before the fix, this would cause a crash when the speculation rules
     46    // tried to match the selector against the link.
     47    getComputedStyle(link).display;
     48 
     49    // If we get here without crashing, the test passes.
     50    assert_true(true, 'No crash occurred');
     51  }, 'selector_matches with link inside closed details should not crash');
     52 
     53  test(() => {
     54    // Create a closed details element with a link inside.
     55    const details = document.createElement('details');
     56    document.body.appendChild(details);
     57 
     58    const summary = document.createElement('summary');
     59    summary.textContent = 'Click to expand';
     60    details.appendChild(summary);
     61 
     62    const link = document.createElement('a');
     63    link.href = 'https://example.com/test2';
     64    link.className = 'toggle-link';
     65    link.textContent = 'Link for toggle test';
     66    details.appendChild(link);
     67 
     68    // Insert a document rule with selector_matches.
     69    const script = document.createElement('script');
     70    script.type = 'speculationrules';
     71    script.textContent = JSON.stringify({
     72      prefetch: [{
     73        source: 'document',
     74        eagerness: 'immediate',
     75        where: { selector_matches: 'a.toggle-link' }
     76      }]
     77    });
     78    document.head.appendChild(script);
     79 
     80    // Rapidly toggle the details element and force style computation.
     81    for (let i = 0; i < 10; i++) {
     82      details.open = !details.open;
     83      getComputedStyle(link).display;
     84    }
     85 
     86    // Ensure details is closed at the end.
     87    details.open = false;
     88    getComputedStyle(link).display;
     89 
     90    // If we get here without crashing, the test passes.
     91    assert_true(true, 'No crash occurred during rapid toggling');
     92  }, 'Rapid toggling of details with selector_matches should not crash');
     93 
     94 </script>
     95 </body>