Skip to content

Document render-blocking with <link rel=expect> #31939

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

Merged

Conversation

mattwoodrow
Copy link
Contributor

@mattwoodrow mattwoodrow commented Aug 9, 2024

0e9bbd9

Document render-blocking with <link rel=expect>
https://bugs.webkit.org/show_bug.cgi?id=268743
<rdar://122797243>

Reviewed by Tim Nguyen.

Implements the render-blocking concept on Document, and the rel=expect attribute for <link>.
https://html.spec.whatwg.org/multipage/dom.html#block-rendering

utils.js changed to generate a unique URL for each parser delay, otherwise we
cache the loads (which may not be spec compliant, but unrelated to
render-blocking).

Render blocking uses the existing code addVisualUpdatePreventedReason to prevent rendering, and rAF.

Some of the test fail because they have no render blocking (since an attempt was
rejected due to a mismatched media query or similar). These tests expect
rendering to happen mid-parsing, but don't due to our existing layer tree
freezing code. I've opted not to change the existing behaviour for now, and only
have this kick in when there is explicit (and active) render blocking elements.

As an optimization, when an <a> element changes, we pass that element into the 'process internal
resource links' algorithm. Rather than doing a tree search for each link looking for matching anchors,
we can just directly check if the link matches the mutated <a>.

* LayoutTests/TestExpectations:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-002-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-004-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-005-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-007-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-009-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-010-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-013-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-014-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-015-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-016-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-017-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-018-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-019-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-020-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-021-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-022-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-023-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-025-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-026-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-028-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-029-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-030-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-031-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-032-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-034-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-035-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-036-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-037-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-038-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/remove-element-unblocks-rendering.optional-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/support/utils.js:
(generateParserDelay):
* LayoutTests/imported/w3c/web-platform-tests/loading/resources/dummy.js: Added.
* LayoutTests/platform/glib/TestExpectations:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::setReadyState):
(WebCore::Document::setVisualUpdatesAllowed):
(WebCore::Document::addVisualUpdatePreventedReason):
(WebCore::Document::removeVisualUpdatePreventedReason):
(WebCore::Document::visualUpdatesSuppressionTimerFired):
(WebCore::Document::setVisualUpdatesAllowedByClient):
(WebCore::Document::suspend):
(WebCore::Document::resume):
(WebCore::Document::allowsAddingRenderBlockedElements const):
(WebCore::Document::isRenderBlocked const):
(WebCore::Document::blockRenderingOn):
(WebCore::Document::unblockRenderingOn):
(WebCore::Document::processInternalResourceLinks):
* Source/WebCore/dom/Document.h:
(WebCore::Document::visualUpdatesAllowed const):
* Source/WebCore/html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::attributeChanged):
(WebCore::HTMLAnchorElement::insertedIntoAncestor):
* Source/WebCore/html/HTMLAnchorElement.h:
* Source/WebCore/html/HTMLAttributeNames.in:
* Source/WebCore/html/HTMLLinkElement.cpp:
(WebCore::ExpectIdTargetObserver::ExpectIdTargetObserver):
(WebCore::ExpectIdTargetObserver::idTargetChanged):
(WebCore::HTMLLinkElement::attributeChanged):
(WebCore::HTMLLinkElement::process):
(WebCore::HTMLLinkElement::processInternalResourceLink):
(WebCore::HTMLLinkElement::unblockRendering):
(WebCore::HTMLLinkElement::removedFromAncestor):
(WebCore::HTMLLinkElement::blocking):
* Source/WebCore/html/HTMLLinkElement.h:
* Source/WebCore/html/HTMLLinkElement.idl:
* Source/WebCore/html/LinkRelAttribute.cpp:
(WebCore::LinkRelAttribute::LinkRelAttribute):
* Source/WebCore/html/LinkRelAttribute.h:

Canonical link: https://commits.webkit.org/282279@main

ff21813

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 wincairo
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ✅ 🧪 wincairo-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ✅ 🧪 mac-wk1 ✅ 🛠 wpe-cairo
✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🧪 vision-wk2
✅ 🛠 tv
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@mattwoodrow mattwoodrow self-assigned this Aug 9, 2024
@mattwoodrow mattwoodrow added the Page Loading For bugs in page loading, including handling of network callbacks. label Aug 9, 2024
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 9, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 9, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from e5a4d5a to 8b06372 Compare August 9, 2024 09:09
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 9, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 11, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from 8b06372 to fc426ec Compare August 11, 2024 23:08
@mattwoodrow mattwoodrow marked this pull request as ready for review August 11, 2024 23:11
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 12, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 12, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from fc426ec to c42f95f Compare August 12, 2024 02:01
@mattwoodrow mattwoodrow changed the title WIP: Document render-blocking with <link rel=expect> Document render-blocking with <link rel=expect> Aug 12, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from c42f95f to 2ab0bf3 Compare August 12, 2024 04:32
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 12, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 14, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from 2ab0bf3 to 7bfb3ba Compare August 14, 2024 02:22
@nt1m nt1m self-requested a review August 14, 2024 04:38
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 14, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 15, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from 7bfb3ba to 6ea2ce8 Compare August 15, 2024 00:42
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from 6ea2ce8 to 11d7d6a Compare August 15, 2024 01:05
Copy link
Member

@nt1m nt1m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add describe the optimization you've done with the anchor elements? Just for posterity, so folks looking at this commit can have the context.

FAIL blocking defers frames until full parsing assert_false: expected false got true
Harness Error (TIMEOUT), message = null

TIMEOUT blocking defers frames until full parsing Test timed out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a follow up for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll file a bug. Something to do with emoji's vs percent-syntax not matching.

I believe it's unrelated to my new code, but would be good to fix.

@@ -1,4 +1,5 @@
function generateParserDelay(seconds = 1) {
seconds += (Math.random() / 10.0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't forget to export to WPT

@@ -83,6 +83,8 @@ class HTMLAnchorElement : public HTMLElement, public URLDecomposition {
String referrerPolicyForBindings() const;
ReferrerPolicy referrerPolicy() const;

Node::InsertedIntoAncestorResult insertedIntoAncestor(InsertionType , ContainerNode& parentOfInsertedTree) override;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Node::InsertedIntoAncestorResult insertedIntoAncestor(InsertionType , ContainerNode& parentOfInsertedTree) override;
Node::InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode& parentOfInsertedTree) override;

@@ -573,6 +655,18 @@ DOMTokenList& HTMLLinkElement::relList()
return *m_relList;
}

DOMTokenList& HTMLLinkElement::blocking()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from 11d7d6a to a58e9ec Compare August 15, 2024 02:24
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Aug 15, 2024
@mattwoodrow mattwoodrow removed the merging-blocked Applied to prevent a change from being merged label Aug 15, 2024
@mattwoodrow mattwoodrow force-pushed the eng/render-blocking-rel-expect branch from a58e9ec to ff21813 Compare August 15, 2024 05:02
@mattwoodrow mattwoodrow added the merge-queue Applied to send a pull request to merge-queue label Aug 15, 2024
https://bugs.webkit.org/show_bug.cgi?id=268743
<rdar://122797243>

Reviewed by Tim Nguyen.

Implements the render-blocking concept on Document, and the rel=expect attribute for <link>.
https://html.spec.whatwg.org/multipage/dom.html#block-rendering

utils.js changed to generate a unique URL for each parser delay, otherwise we
cache the loads (which may not be spec compliant, but unrelated to
render-blocking).

Render blocking uses the existing code addVisualUpdatePreventedReason to prevent rendering, and rAF.

Some of the test fail because they have no render blocking (since an attempt was
rejected due to a mismatched media query or similar). These tests expect
rendering to happen mid-parsing, but don't due to our existing layer tree
freezing code. I've opted not to change the existing behaviour for now, and only
have this kick in when there is explicit (and active) render blocking elements.

As an optimization, when an <a> element changes, we pass that element into the 'process internal
resource links' algorithm. Rather than doing a tree search for each link looking for matching anchors,
we can just directly check if the link matches the mutated <a>.

* LayoutTests/TestExpectations:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-002-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-004-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-005-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-007-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-009-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-010-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-013-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-014-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-015-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-016-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-017-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-018-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-019-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-020-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-021-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-022-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-023-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-025-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-026-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-028-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-029-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-030-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-031-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-032-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-034-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-035-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-036-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-037-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/element-render-blocking-038-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/remove-element-unblocks-rendering.optional-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/dom/render-blocking/support/utils.js:
(generateParserDelay):
* LayoutTests/imported/w3c/web-platform-tests/loading/resources/dummy.js: Added.
* LayoutTests/platform/glib/TestExpectations:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::setReadyState):
(WebCore::Document::setVisualUpdatesAllowed):
(WebCore::Document::addVisualUpdatePreventedReason):
(WebCore::Document::removeVisualUpdatePreventedReason):
(WebCore::Document::visualUpdatesSuppressionTimerFired):
(WebCore::Document::setVisualUpdatesAllowedByClient):
(WebCore::Document::suspend):
(WebCore::Document::resume):
(WebCore::Document::allowsAddingRenderBlockedElements const):
(WebCore::Document::isRenderBlocked const):
(WebCore::Document::blockRenderingOn):
(WebCore::Document::unblockRenderingOn):
(WebCore::Document::processInternalResourceLinks):
* Source/WebCore/dom/Document.h:
(WebCore::Document::visualUpdatesAllowed const):
* Source/WebCore/html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::attributeChanged):
(WebCore::HTMLAnchorElement::insertedIntoAncestor):
* Source/WebCore/html/HTMLAnchorElement.h:
* Source/WebCore/html/HTMLAttributeNames.in:
* Source/WebCore/html/HTMLLinkElement.cpp:
(WebCore::ExpectIdTargetObserver::ExpectIdTargetObserver):
(WebCore::ExpectIdTargetObserver::idTargetChanged):
(WebCore::HTMLLinkElement::attributeChanged):
(WebCore::HTMLLinkElement::process):
(WebCore::HTMLLinkElement::processInternalResourceLink):
(WebCore::HTMLLinkElement::unblockRendering):
(WebCore::HTMLLinkElement::removedFromAncestor):
(WebCore::HTMLLinkElement::blocking):
* Source/WebCore/html/HTMLLinkElement.h:
* Source/WebCore/html/HTMLLinkElement.idl:
* Source/WebCore/html/LinkRelAttribute.cpp:
(WebCore::LinkRelAttribute::LinkRelAttribute):
* Source/WebCore/html/LinkRelAttribute.h:

Canonical link: https://commits.webkit.org/282279@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/render-blocking-rel-expect branch from ff21813 to 0e9bbd9 Compare August 15, 2024 07:59
@webkit-commit-queue
Copy link
Collaborator

Committed 282279@main (0e9bbd9): https://commits.webkit.org/282279@main

Reviewed commits have been landed. Closing PR #31939 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 0e9bbd9 into WebKit:main Aug 15, 2024
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Page Loading For bugs in page loading, including handling of network callbacks.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants