8000 script: Unify script-based "update the rendering" and throttle it to 60 FPS by mrobinson · Pull Request #38431 · servo/servo · GitHub
[go: up one dir, main page]

Skip to content

Conversation

mrobinson
Copy link
Member
@mrobinson mrobinson commented Aug 2, 2025

Instead of running "update the rendering" at every IPC message, only run
it when a timeout has occured in script. In addition, avoid updating the
rendering if a rendering update isn't necessary. This should greatly
reduce the amount of processing that has to happen in script.

Because we are running many fewer calls to "update the rendering" it is
reasonable now to ensure that these always work the same way. In
particular, we always run rAF and update the animation timeline when
updating the ernder

In addition, pull the following things out of reflow:

  • Code dealing with informing the Constellation that a Pipeline has
    become Idle when waiting for a screenshot.
  • Detecting when it is time to fulfill the document.fonts.ready
    promise.

The latter means that reflow can never cause a garbage collection,
making timing of reflows more consistent and simplifying many callsites
that need to do script queries.

Followup changes will seek to simplify the way that ScriptThread-driven
animation timeouts happen even simpler.

Testing: In general, this should not change testable behavior so much, though it
does seem to fix one test. The main improvement here should be that
the ScriptThread does less work.

@mrobinson mrobinson force-pushed the update-the-rendering branch from 95809ce to b857773 Compare August 2, 2025 16:33
@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Aug 2, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Aug 2, 2025
Copy link
github-actions bot commented Aug 2, 2025

🔨 Triggering try run (#16695594746) for Linux (WPT)

@mrobinson
Copy link
Member Author

Marked as draft because I want to add more documentation to the code before landing this.

Copy link
github-actions bot commented Aug 2, 2025

Test results for linux-wpt from try job (#16695594746):

Flaky unexpected result (22)
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 1
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 2
  • FAIL [expected PASS] /css/css-flexbox/flex-item-content-is-min-width-max-content.html
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-stretch: '90%' should prefer '90% 100%' over '50% 80%'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

    • FAIL [expected PASS] subtest: Matching font-style: 'oblique 21deg' should prefer 'oblique 20deg' over 'oblique 10deg'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

  • OK /css/cssom-view/elementsFromPoint-iframes.html (#38362)
    • FAIL [expected PASS] subtest: elementsFromPoint on the root document for points in iframe elements

      assert_equals: document.elementsFromPoint(51,51) expected "IFRAME#scrollableIframe, IFRAME#iframe, BODY, HTML" but got "IFRAME#scrollableIframe, DIV#div, BODY, HTML, IFRAME#iframe, BODY, HTML"
      

  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Cross-site
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • PASS [expected FAIL] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • TIMEOUT [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with empty fragments should work.

      Test timed out
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with "top" fragments should work.

      Test timed out
      

  • PASS [expected FAIL] /html/rendering/widgets/appearance/appearance-animation-002.html
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-link-click.html (#32664)
    • FAIL [expected PASS] subtest: Navigating iframe loading='lazy' before it is loaded: link click

      uncaught exception: Error: assert_equals: expected "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?nav" but got "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?src"
      

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK /html/semantics/forms/historical.html (#28568)
    • PASS [expected FAIL] subtest: <input name=isindex> should not be supported
  • CRASH [expected OK] /html/semantics/forms/the-fieldset-element/disabled-003.html (#31730)
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • TIMEOUT [expected PASS] /resize-observer/iframe-same-origin.html
  • TIMEOUT [expected OK] /resource-timing/tentative/document-initiated.html (#37785)
  • TIMEOUT /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)
  • FAIL [expected PASS] /shadow-dom/shadow-style-invalidation-vw-units.html
Stable unexpected results that are known to be intermittent (23)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • FAIL [expected PASS] subtest: Delete layer invalidates @font-face

      assert_equals: expected "220px" but got "133px"
      

  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
    • PASS [expected FAIL] subtest: Link with onclick navigation and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/008.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • FAIL [expected PASS] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src=''

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-id-top.html (#21338)
    • FAIL [expected PASS] subtest: Fragment Navigation: TOP is a valid element id, which overrides navigating to top of the document

      assert_equals: expected 200 but got 0
      

  • OK /html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-top.html (#21351)
    • FAIL [expected PASS] subtest: Fragment Navigation: When fragid is TOP scroll to the top of the document

      assert_not_equals: got disallowed value 0
      

  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • PASS [expected FAIL] subtest: traversing history must also traverse hash changes
  • PASS [expected FAIL] /html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html (#30063)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      assert_equals: expected Element node <input autofocus=""></input> but got Element node <body></body>
      

    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      assert_equals: expected Element node <area autofocus="" href="/common/blank.html"></area> but got Element node <body>
      <img src="/media/poster.png" usemap="#map">
      <map n...
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
  • OK /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: Basic test (normal form)
  • OK /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: CORS (style): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.css?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=style should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: 404 (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.js?pipe=status%28404%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: CORS (xhr): main
    • PASS [expected FAIL] subtest: Decode-error (style): main
    • PASS [expected FAIL] subtest: MIME-error (script): main
  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK /resize-observer/eventloop.html (#33599)
    • PASS [expected FAIL] subtest: test0: multiple notifications inside same event loop
  • TIMEOUT [expected OK] /webmessaging/without-ports/018.html (#24485)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, javascript:

      Test timed out
      

Stable unexpected results (3)
  • OK /dom/events/scrolling/scroll-event-fired-to-element.html
    • FAIL [expected PASS] subtest: scrollTop and scrollLeft should fire scroll event.

      promise_test: Unhandled rejection with value: "No scroll event received for target [object HTMLDivElement]"
      

    • FAIL [expected PASS] subtest: scrollTop and scrollLeft when scrolling above maximum offset.

      promise_test: Unhandled rejection with value: "No scroll event received for target [object HTMLDivElement]"
      

  • OK /dom/events/scrolling/scroll-event-fired-to-iframe.html
    • FAIL [expected PASS] subtest: scrollX and scrollY when scrolling above maximum Scroll.

      promise_test: Unhandled rejection with value: "No scroll event received for target [object Window]"
      

  • OK /intersection-observer/callback-cross-realm-report-exception.html
    • FAIL [expected PASS] subtest: IntersectionObserver reports the exception from its callback in the callback's global object

      assert_array_equals: lengths differ, expected array ["frame1"] length 1, got [] length 0
      

Copy link
github-actions bot commented Aug 2, 2025

⚠️ Try run (#16695594746) failed.

@sagudev
Copy link
Member
sagudev commented Aug 3, 2025

The main improvement here should be that the ScriptThread does more work.

This PR introduces script driven "update the rendering", right? We need to think what would that mean for #37776.

@mrobinson
Copy link
Member Author
mrobinson commented Aug 3, 2025

The main improvement here should be that the ScriptThread does more work.

This PR introduces script driven "update the rendering", right? We need to think what would that mean for #37776.

Sorry, I meant to write "less work." The ScriptThread already does its own "update the rendering" calls when it doesn't expect to receive ticks from the renderer (when it isn't producing display lists). In addition, the ScriptThread currently runs "update the rendering" whenever receiving an IPC message, but without running rAFs. This change makes it so that the ScriptThread runs "update the rendering" in a spec-compliant way (running rAFs), but driven by a timer and only when it detects that it's necessary. I think it brings the ScriptThread-driven "update the rendering" closer to the specification.

@mrobinson mrobinson force-pushed the update-the-rendering branch from b857773 to 48e14be Compare August 3, 2025 09:39
@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Aug 3, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Aug 3, 2025
Copy link
github-actions bot commented Aug 3, 2025

🔨 Triggering try run (#16703627347) for Linux (WPT)

Copy link
github-actions bot commented Aug 3, 2025

Test results for linux-wpt from try job (#16703627347):

Flaky unexpected result (25)
  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: Revoke blob URL after calling fetch, fetch should succeed

      promise_test: Unhandled rejection with value: object "TypeError: Network error occurred"
      

  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • FAIL [expected PASS] /_mozilla/gfx-rs-gecko/descriptor-ranges.html (#23258)
  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-metadata-003.xht
  • FAIL [expected PASS] /css/css-fonts/downloadable-font-scoped-to-document.html
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-weight: '399' should prefer '500 501' over '502 510'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 20deg' should prefer 'oblique -40deg -30deg' over 'italic'
    • FAIL [expected PASS] subtest: Matching font-style: 'oblique 21deg' should prefer 'oblique 21deg' over 'oblique 30deg 60deg'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

    • FAIL [expected PASS] subtest: Matching font-style: 'oblique -21deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.tentative.https.window.html (#35176)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Cross-site
  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • FAIL [expected PASS] subtest: traversing history must also traverse hash changes

      assert_equals: (this could cause other failures later on) expected "" but got "test"
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with non-existent fragments should work.

      Test timed out
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected FAIL] subtest: Element with tabindex should support autofocus

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Non-HTMLElement should not support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus should support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped
    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: Basic test (normal form)
  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • PASS [expected FAIL] subtest: text/plain: Basic test (normal form)
  • CRASH [expected OK] /html/semantics/forms/the-fieldset-element/di 8000 sabled-003.html (#31730)
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • TIMEOUT /preload/preload-resource-match.https.html (#38088)
    • TIMEOUT [expected FAIL] subtest: Loading script (use-credentials) with link (no-cors) should discard the preloaded response

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Loading script (use-credentials) with link (anonymous) should discard the preloaded response
  • TIMEOUT [expected OK] /resource-timing/nested-context-navigations-iframe.html (#24311)
    • TIMEOUT [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent, even after history navigations by the parent

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Test that iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe refreshes are not observable by the parent
  • TIMEOUT [expected OK] /resource-timing/tentative/document-initiated.html (#37785)
  • ERROR /service-workers/idlharness.https.any.html (#36250)
    • PASS [expected TIMEOUT] subtest: ServiceWorkerContainer interface: operation register((TrustedScriptURL or USVString), optional RegistrationOptions)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation enable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation disable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation setHeaderValue(ByteString)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation getState()
  • OK [expected TIMEOUT] /webmessaging/without-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • TIMEOUT [expected OK] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • TIMEOUT [expected PASS] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      Test timed out
      

  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • ERROR [expected OK] /workers/semantics/run-a-worker/003.html (#22765)
Stable unexpected results that are known to be intermittent (22)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 1
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 2
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/empty-iframe-load-event.html (#29066)
    • FAIL [expected PASS] subtest: Check execution order from nested timeout

      assert_equals: Expected nested setTimeout to run second expected true but got false
      

    • FAIL [expected PASS] subtest: Check execution order on load handler

      assert_equals: Expected onload to run first expected false but got true
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html (#29048)
    • FAIL [expected PASS] subtest: Navigating to a different document with location.href

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?1" but got "about:blank"
      

    • FAIL [expected PASS] subtest: Navigating to a different document with location.assign

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?1" but got "about:blank"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • FAIL [expected PASS] subtest: load event does not fire on window.open('about:blank')

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-reload-location-reload.html (#32595)
    • FAIL [expected PASS] subtest: Reloading iframe loading='lazy' before it is loaded: location.reload

      uncaught exception: Error: assert_equals: expected "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?src" but got "about:blank"
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: Basic test (normal form)
  • OK /preload/prefetch-document.html (#37210)
    • PASS [expected FAIL] subtest: different-site document prefetch with 'as=document' should not be consumed
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: CORS (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • FAIL [expected PASS] subtest: 404 (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.js?pipe=status%28404%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: CORS (script): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.js?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: CORS (xhr): main
    • FAIL [expected PASS] subtest: Decode-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=header%28Content-Type%2Ctext%2Fjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: MIME-error (script): main
  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK /resize-observer/eventloop.html (#33599)
    • PASS [expected FAIL] subtest: test0: multiple notifications inside same event loop
  • OK /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: X Stitched sine-wave buffers at sample rate 44100 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...] with an element-wise tolerance of {"absoluteThreshold":0.000090957,"relativeThreshold":0}. Index Actual Expected AbsError RelError Test threshold [15300] 2.3574548532783555e-39 -8.2017236948013306e-1 8.2017236948013306e-1 1.0000000000000000e+0 9.0957000000000003e-5 [15301] -2.1671967605912945e-12 -8.5440337657928467e-1 8.5440337657711751e-1 9.9999999999746358e-1 9.0957000000000003e-5 Max AbsError of 8.5440337657711751e-1 at index of 15301. Max RelError of 1.0000000000000000e+0 at index of 15300.

      assert_true: expected true got false
      

    • FAIL [expected PASS] subtest: X SNR (41.9644756054668 dB) is not greater than or equal to 85.58. Got 41.9644756054668.

      assert_true: expected true got false
      

Copy link
github-actions bot commented Aug 3, 2025

✨ Try run (#16703627347) succeeded.

@sagudev
Copy link
Member
sagudev commented Aug 3, 2025

The main improvement here should be that the ScriptThread does more work.

This PR introduces script driven "update the rendering", right? We need to think what would that mean for #37776.

Sorry, I meant to write "less work." The ScriptThread already does its own "update the rendering" calls when it doesn't expect to receive ticks from the renderer (when it isn't producing display lists). In addition, the ScriptThread currently runs "update the rendering" whenever receiving an IPC message, but without running rAFs. This change makes it so that the ScriptThread runs "update the rendering" in a spec-compliant way (running rAFs), but driven by a timer and only when it detects that it's necessary. I think it brings the ScriptThread-driven "update the rendering" closer to the specification.

Ah, thanks for explanation. I see the bigger picture now.

@mrobinson mrobinson force-pushed the update-the-rendering branch from 48e14be to cbf0858 Compare August 3, 2025 17:21
@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Aug 3, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Aug 3, 2025
Copy link
github-actions bot commented Aug 3, 2025

🔨 Triggering try run (#16707542911) for Linux (WPT)

Copy link
github-actions bot commented Aug 3, 2025

Test results for linux-wpt from try job (#16707542911):

Flaky unexpected result (25)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • TIMEOUT [expected PASS] subtest: Fetching a blob URL immediately before revoking it works in <script> tags.

      Test timed out
      

  • OK /content-security-policy/frame-ancestors/frame-ancestors-path-ignored.window.html (#36468)
    • FAIL [expected PASS] subtest: A 'frame-ancestors' CSP directive with a URL that includes a path should be ignored.

      assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
      

  • FAIL [expected PASS] /css/WOFF2/datatypes-invalid-base128-001.xht
  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-licensee-002.xht
  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-uniqueid-006.xht
  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • FAIL [expected PASS] subtest: Delete layer invalidates @font-face

      assert_equals: expected "220px" but got "133px"
      

  • FAIL [expected PASS] /css/css-flexbox/table-item-flex-percentage-width.html
  • FAIL [expected PASS] /css/css-fonts/font-variation-settings-descriptor-02.html
  • OK /css/css-fonts/variations/font-weight-matching.html
    • FAIL [expected PASS] subtest: Test @font-face matching for weight 99

      assert_approx_equals: @font-face should be mapped to CSSTest Weights 900. expected 90 +/- 2 but got 180
      

    • FAIL [expected PASS] subtest: Test @font-face matching for weight 100

      assert_approx_equals: @font-face should be mapped to CSSTest Weights 900. expected 90 +/- 2 but got 180
      

    • FAIL [expected PASS] subtest: Test @font-face matching for weight 249

      assert_approx_equals: @font-face should be mapped to CSSTest Weights 900. expected 90 +/- 2 but got 180
      

  • FAIL [expected PASS] /css/css-pseudo/marker-font-variant-numeric-default.html
  • FAIL [expected PASS] /css/css-will-change/will-change-transform-huge-offset-scrolled.html
  • OK /css/cssom-view/elementsFromPoint-iframes.html (#38362)
    • PASS [expected FAIL] subtest: elementsFromPoint on the root document for points in iframe elements
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Single value - name is missing
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-user
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Cross-site
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html (#29048)
    • FAIL [expected PASS] subtest: Navigating to a different document with location.href

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?1" but got "about:blank"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • FAIL [expected PASS] subtest: Same-Document Referrer from Refresh

      assert_equals: original page loads expected "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section#section"
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • ERROR /html/semantics/embedded-content/image-maps/image-map-processing-model/hash-name-reference.html (#16179)
    • FAIL [expected PASS] subtest: HTML (standards) IMG usemap="no-hash-name"

      assert_equals: expected Element node <img src="/images/threecolors.png" usemap="no-hash-name">... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="no-hash-na... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) IMG usemap="no-hash-id"

      assert_equals: expected Element node <img src="/images/threecolors.png" usemap="no-hash-id"></... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="no-hash-id... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#hash-name... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#hash-id">... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#non-map-w... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#non-map-w... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#two-maps-... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • FAIL [expected PASS] subtest: HTML (standards) OBJECT usemap=undefined

      assert_equals: expected Element node <object data="/images/threecolors.png" usemap="#two-maps-... but got Element node <html><head><meta charset="utf-8">
      <title>parsing a hash-...
      

    • And 28 more unexpected results...
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: Basic test (normal form)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: \r\n in value (normal form)
  • TIMEOUT /preload/preload-resource-match.https.html (#38088)
    • TIMEOUT [expected FAIL] subtest: Loading script (use-credentials) with link (no-cors) should discard the preloaded response

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Loading script (use-credentials) with link (anonymous) should discard the preloaded response
  • CRASH [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • ERROR [expected OK] /workers/constructors/Worker/Worker-constructor.html (#22991)
Stable unexpected results that are known to be intermittent (21)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/008.html (#24456)
    • FAIL [expected PASS] subtest: Link with onclick form submit to javascript url and href navigation

      assert_equals: expected "href" but got "click"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • FAIL [expected PASS] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'

      assert_unreached: load should not be fired Reached unreachable code
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected FAIL] subtest: Element with tabindex should support autofocus

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Non-HTMLElement should not support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus should support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped
    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • OK /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK /html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm (#37173)
    • PASS [expected FAIL] subtest: default object size after src is removed
  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • OK /preload/prefetch-document.html (#37210)
    • PASS [expected FAIL] subtest: different-site document prefetch with 'as=document' should not be consumed
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: CORS (style): main
    • FAIL [expected PASS] subtest: CORS (script): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.js?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: CORS (xhr): main
    • FAIL [expected PASS] subtest: Decode-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=header%28Content-Type%2Ctext%2Fjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK /resize-observer/eventloop.html (#33599)
    • PASS [expected FAIL] subtest: test0: multiple notifications inside same event loop
    • FAIL [expected PASS] subtest: test1: depths of shadow roots

      assert_unreached: Timed out waiting for notification. (1000ms) Reached unreachable code
      

  • OK /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: X Stitched sine-wave buffers at sample rate 44100 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...] with an element-wise tolerance of {"absoluteThreshold":0.000090957,"relativeThreshold":0}. Index Actual Expected AbsError RelError Test threshold [15300] 2.4011001586914063e+0 -8.2017236948013306e-1 3.2212725281715393e+0 3.9275555334951671e+0 9.0957000000000003e-5 [15301] -2.1671967605912945e-12 -8.5440337657928467e-1 8.5440337657711751e-1 9.9999999999746358e-1 9.0957000000000003e-5 Max AbsError of 3.2212725281715393e+0 at index of 15300. Max RelError of 3.9275555334951671e+0 at index of 15300.

      assert_true: expected true got false
      

    • FAIL [expected PASS] subtest: X SNR (32.97827391616376 dB) is not greater than or equal to 85.58. Got 32.97827391616376.

      assert_true: expected true got false
      

Copy link
github-actions bot commented Aug 3, 2025

✨ Try run (#16707542911) succeeded.

@mrobinson mrobinson marked this pull request as ready for review August 3, 2025 18:13
Copy link
Member
@sagudev sagudev left a comment

Choose a reason for hiding this comment

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

I like the way this is clearing up. This PR also improves situation with #38327, there is still FPS drop, but less, so it might not be observed with not enough bunnies.

Comment on lines +2339 to +2341
if self.font_context.web_fonts_still_loading() != 0 {
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

thought: Would it make sense to use fonts.waiting_to_fullfill_promise here?

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree that this makes sense, though I would prefer to do it in a followup as I'm afraid of introducing too many more behavior changes in this one PR.

Comment on lines +17 to +18
window.requestAnimationFrame(() => {
window.requestAnimationFrame(test.step_func_done(function () {
Copy link
Member

Choose a reason for hiding this comment

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

Hm, why do we need 2 rAFs to make this work. That does not seem right.

On related note, why isn't this tests upstreamed to WPT? I do not see anything servo specific.

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe this needs two frames because the resize needs to be processed according to the specification in "update the rendering":

  1. Forced layout: The <iframe> element resizes, but outside of "update the rendering."
  2. First requestAnimationFrame callback, the Document inside the <iframe> element is resized according to the <iframe> resize during "update the rendering".
  3. Second requestAnimationFrame callback: The corresponding media-dependent styles are applied after the Document is resized.

It's pretty common in WPT that these sort of tests wait for two animation frames before verifying behavior. Perhaps this could be improved, but maybe it's a bit outside the scope of this change. I think this test was passing accidentally before because all IPC messages were forcing "update the rendering" between rAF callbacks, which isn't spec behavior.

Copy link
Member

Choose a reason for hiding this comment

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

This works without any rAFs in both firefox and chromium:

window.onload = test.step_func(function() {
  var frame = document.getElementById("myframe");
  var frameDoc = frame.contentWindow.document;
  var element = frameDoc.getElementById("testelement");
  assert_equals(frame.contentWindow.getComputedStyle(element).backgroundColor, "rgb(255, 0, 0)");
  frame.width = "300";
  frameDoc.documentElement.offsetWidth; // Force layout
  test.step_func_done(function () {
    assert_equals(frame.contentWindow.getComputedStyle(element).backgroundColor, "rgb(0, 255, 0)");
  })()
});

Copy link
Member Author

Choose a reason for hiding this comment

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

I suspect there is something wrong about the way we are processing updates here (either the restyle or the media query update) or else Firefox and Chromium have a more optimized implementation. In any case, I think this issue existed before my change.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed, we should open issue about that.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've opened #38446 for this.

@mrobinson mrobinson force-pushed the update-the-rendering branch 2 times, most recently from 5c370be to 17748c6 Compare August 4, 2025 08:57
@mrobinson mrobinson enabled auto-merge August 4, 2025 09:27
@mrobinson
Copy link
Member Author

@sagudev Thank you for the review!

@mrobinson mrobinson added this pull request to the merge queue Aug 4, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Aug 4, 2025
@sagudev
Copy link
Member
sagudev commented Aug 4, 2025

TIMEOUT [expected PASS] /resize-observer/iframe-same-origin.html

Might be related to #38446

@mrobinson
Copy link
Member Author

The issue here seems to be that when a ResizeObserver starts observing, we need to run "update the rendering" because it should deliver an event before a resize happens. It seems that we need to check to see if we've started observing in Document::needs_rendering_update().

…60 FPS

Instead of running "update the rendering" at every IPC message, only run
it when a timeout has occured in script. In addition, avoid updating the
rendering if a rendering update isn't necessary. This should greatly
reduce the amount of processing that has to happen in script.

Because we are running many fewer calls to "update the rendering" it is
reasonable now to ensure that these always work the same way. In
particular, we always run rAF and update the animation timeline when
updating the ernder

In addition, pull the following things out of reflow:

 - Code dealing with informing the Constellation that a Pipeline has
   become Idle when waiting for a screenshot.
 - Detecting when it is time to fulfill the `document.fonts.ready`
   promise.

The latter means that reflow can never cause a garbage collection,
making timing of reflows more consistent and simplifying many callsites
that need to do script queries.

Followup changes will seek to simplify the way that ScriptThread-driven
animation timeouts happen even simpler.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
@mrobinson mrobinson force-pushed the update-the-rendering branch from 17748c6 to 8b8e081 Compare August 4, 2025 15:51
@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Aug 4, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Aug 4, 2025
Copy link
github-actions bot commented Aug 4, 2025

🔨 Triggering try run (#16727928517) for Linux (WPT)

Copy link
github-actions bot commented Aug 4, 2025

Test results for linux-wpt from try job (#16727928517):

Flaky unexpected result (29)
  • TIMEOUT [expected OK] /FileAPI/blob/Blob-bytes.any.worker.html
  • TIMEOUT [expected OK] /FileAPI/file/File-constructor-endings.html
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • TIMEOUT [expected PASS] subtest: Fetching a blob URL immediately before revoking it works in &lt;script&gt; tags.

      Test timed out
      

  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: Revoke blob URL after calling fetch, fetch should succeed

      promise_test: Unhandled rejection with value: object "TypeError: Network error occurred"
      

  • TIMEOUT [expected OK] /WebCryptoAPI/getRandomValues.any.html
  • FAIL [expected PASS] /_mozilla/css/letter_spacing_a.html
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • TIMEOUT /content-security-policy/inheritance/location-reload.html
    • FAIL [expected PASS] subtest: location.reload() of empty iframe.

      assert_equals: Image should be blocked by CSP after reload. expected "img blocked" but got "img loaded"
      

  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-trademark-021.xht
  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • FAIL [expected PASS] subtest: Delete layer invalidates @font-face

      assert_equals: expected "220px" but got "133px"
      

  • FAIL [expected PASS] /css/css-text/shaping/shaping-010.html
  • FAIL [expected PASS] /css/css-text/text-transform/text-transform-upperlower-014.html
  • OK /html/browsers/browsing-the-web/navigating-across-documents/008.html (#24456)
    • FAIL [expected PASS] subtest: Link with onclick form submit to javascript url and href navigation

      assert_equals: expected "href" but got "click"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/empty-iframe-load-event.html (#29066)
    • FAIL [expected PASS] subtest: Check execution order from nested timeout

      assert_equals: Expected nested setTimeout to run second expected true but got false
      

    • FAIL [expected PASS] subtest: Check execution order on load handler

      assert_equals: Expected onload to run first expected false but got true
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html (#29048)
    • PASS [expected FAIL] subtest: Navigating to a different document with form submission
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • FAIL [expected PASS] subtest: load event does not fire on window.open('about:blank')

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • PASS [expected FAIL] subtest: Cross-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • FAIL [expected PASS] subtest: Same-Document Referrer from Refresh

      assert_equals: original page loads expected "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section#section"
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_3.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/browsers/sandboxing/sandbox-initial-empty-document-toward-same-origin.html (#35948)
  • PASS [expected FAIL] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with non-existent fragments should work.

      Test timed out
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with "top" fragments should work.

      Test timed out
      

  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: single quote in value (normal form)
  • FAIL [expected PASS] /shadow-dom/shadow-style-invalidation-vw-units.html
  • CRASH [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
  • OK [expected TIMEOUT] /webmessaging/with-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
Stable unexpected results that are known to be intermittent (25)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Single value - name is missing
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Cross-site
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Same site
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • PASS [expected FAIL] /html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html (#30063)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with empty fragments should work.

      Test timed out
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected PASS] subtest: Non-HTMLElement should not support autofocus

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus should support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped
    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-reload-location-reload.html (#32595)
    • FAIL [expected PASS] subtest: Reloading iframe loading='lazy' before it is loaded: location.reload

      uncaught exception: Error: assert_equals: expected "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?src" but got "about:blank"
      

  • OK /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK /html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm (#37173)
    • PASS [expected FAIL] subtest: default object size after src is removed
  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /preload/prefetch-document.html (#37210)
    • PASS [expected FAIL] subtest: different-site document prefetch with 'as=document' should not be consumed
  • OK /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • FAIL [expected PASS] subtest: 404 (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.js?pipe=status%28404%29&amp;label=script should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: 404 (xhr): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=status%28404%29&amp;label=xhr should be loaded expected a number greater than 0 but got 0
      

  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK /resize-observer/eventloop.html (#33599)
    • PASS [expected FAIL] subtest: test0: multiple notifications inside same event loop
    • FAIL [expected PASS] subtest: test1: depths of shadow roots

      assert_unreached: Timed out waiting for notification. (1000ms) Reached unreachable code
      

  • TIMEOUT [expected OK] /resource-timing/tentative/document-initiated.html (#37785)
  • OK /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: X Stitched sine-wave buffers at sample rate 44100 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...] with an element-wise tolerance of {"absoluteThreshold":0.000090957,"relativeThreshold":0}. Index Actual Expected AbsError RelError Test threshold [15300] 1.5721325000000000e+5 -8.2017236948013306e-1 1.5721407017236948e+5 1.9168418252375381e+5 9.0957000000000003e-5 [15301] -2.1671967605912945e-12 -8.5440337657928467e-1 8.5440337657711751e-1 9.9999999999746358e-1 9.0957000000000003e-5 Max AbsError of 1.5721407017236948e+5 at index of 15300. Max RelError of 1.9168418252375381e+5 at index of 15300.

      assert_true: expected true got false
      

    • FAIL [expected PASS] subtest: X SNR (-60.495742285161214 dB) is not greater than or equal to 85.58. Got -60.495742285161214.

      assert_true: expected true got false
      

  • OK [expected TIMEOUT] /webmessaging/without-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • ERROR [expected OK] /workers/constructors/Worker/Worker-constructor.html (#22991)

Copy link
github-actions bot commented Aug 4, 2025

✨ Try run (#16727928517) succeeded.

@mrobinson mrobinson enabled auto-merge August 4, 2025 16:19
@mrobinson mrobinson added this pull request to the merge queue Aug 4, 2025
Merged via the queue into servo:main with commit 9416251 Aug 4, 2025
54 checks passed
@mrobinson mrobinson deleted the update-the-rendering branch August 4, 2025 17:26
PotatoCP added a commit to PotatoCP/servo that referenced this pull request Aug 6, 2025
…60 FPS (servo#38431) (wd)

{"fail_fast": false, "matrix": [{"name": "Linux (WPT)", "workflow": "linux", "wpt": true, "profile": "release", "unit_tests": false, "build_libservo": false, "bencher": false, "build_args": "", "wpt_args": "./tests/wpt/tests/webdriver/tests/classic/ --product servodriver --headless --processes 1", "number_of_wpt_chunks": 2}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0