-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix element hash fallback in iframes
The text directive element-id fallback tries to scroll to the element-id if a text match wasn't found. It does so in PerformPreRafActions since element fragments cause focus which can execute script. Invoke(), where the text fragment performs its text search, occurs from lifecycle updates where script execution is forbidden. Text directives used to be limited to main-frames but were enabled explicitly for iframes in https://crrev.com/a71830a90b72f0a613fe9. However, PerformPreRafActions wasn't updated to call into the FragmentAnchor of an iframe We also need to strip the fragment directives in ElementFragmentAnchor::TryCreate. In cases where a text fragment is successfully created, the element id fallback works by creating an ElementFragmentAnchor from inside TextFragmentAnchor. However, if the TextFragmentAnchor is blocked or not parsed correctly, the URL passed to ElementFragmentAnchor in FragmentDirective::TryCreate will still include the directives. A test for this was added in the new same-document.tests.html Bug: 1260135 Change-Id: Ib3f19b462016d34cc41d21b05933aa9cb822a9b8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3224519 Commit-Queue: David Bokan <[email protected]> Reviewed-by: Robert Flack <[email protected]> Cr-Commit-Position: refs/heads/main@{#933575}
- Loading branch information
1 parent
5f0a02b
commit c8131af
Showing
3 changed files
with
122 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<!doctype html> | ||
<title>Same document navigation to text fragment directives</title> | ||
<meta charset=utf-8> | ||
<link rel="help" href="https://wicg.github.io/ScrollToTextFragment/"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script> | ||
function reset() { | ||
location.hash = ''; | ||
window.scrollTo(0, 0); | ||
} | ||
|
||
function isInViewport(element) { | ||
const viewportRect = { | ||
left: visualViewport.offsetLeft, | ||
top: visualViewport.offsetTop, | ||
right: visualViewport.offsetLeft + visualViewport.width, | ||
bottom: visualViewport.offsetTop + visualViewport.height | ||
}; | ||
|
||
const elementRect = element.getBoundingClientRect(); | ||
const elementCenter = { | ||
x: elementRect.left + elementRect.width / 2, | ||
y: elementRect.top + elementRect.height / 2 | ||
}; | ||
|
||
return elementCenter.x > viewportRect.left && | ||
elementCenter.x < viewportRect.right && | ||
elementCenter.y > viewportRect.top && | ||
elementCenter.y < viewportRect.bottom; | ||
} | ||
|
||
function runTests() { | ||
// Ensure a simple text directive works correctly when navigated to the | ||
// same document using `location.hash`. | ||
promise_test(async t => { | ||
assert_implements(document.fragmentDirective, 'Text directive not implemented'); | ||
reset(); | ||
|
||
location.hash = ':~:text=line%20of%20text'; | ||
await t.step_wait(() => window.scrollY > 0, "Wait for scroll"); | ||
assert_true(isInViewport(document.getElementById('text')), 'Scrolled to text'); | ||
}, 'Basic text directive navigation'); | ||
|
||
// Test that we correctly fallback to the element id when we have a text | ||
// directive that doesn't match any text in the page. | ||
promise_test(async t => { | ||
assert_implements(document.fragmentDirective, 'Text directive not implemented'); | ||
reset(); | ||
|
||
location.hash = 'elementid:~:text=textDoesntExist'; | ||
await t.step_wait(() => window.scrollY > 0, "Wait for scroll"); | ||
assert_true(isInViewport(document.getElementById('elementid')), 'Scrolled to `elementid`'); | ||
}, 'Basic element id fallback'); | ||
|
||
// Test that we correctly fallback to the element id when we have a text | ||
// directive that's malformed and won't be parsed. | ||
promise_test(async t => { | ||
assert_implements(document.fragmentDirective, 'Text directive not implemented'); | ||
reset(); | ||
|
||
location.hash = 'elementid:~:text=,,,,,'; | ||
await t.step_wait(() => window.scrollY > 0, "Wait for scroll"); | ||
assert_true(isInViewport(document.getElementById('elementid')), 'Scrolled to `elementid`'); | ||
}, 'Malformed text directive element id fallback'); | ||
} | ||
</script> | ||
<style> | ||
div { | ||
margin: 200vh 0 200vh 0; | ||
} | ||
</style> | ||
<body onload="runTests()"> | ||
<div id="text"> | ||
This is a line of text. | ||
</div> | ||
<div id="elementid"> | ||
This div has an id: 'elementid'. | ||
</div> | ||
</body> |