Skip to content

script: Deliver animation frames to dedicated workers - #46232

Merged
Taym95 merged 5 commits into
servo:mainfrom
Taym95:script-dedicated-worker-animation-frames
Aug 6, 2026
Merged

Taym95 merged 5 commits into
servo:mainfrom
Taym95:script-dedicated-worker-animation-frames

Conversation

@Taym95

@Taym95 Taym95 commented Jul 3, 2026

Copy link
Copy Markdown
Member

this exposess AnimationFrameProvider on DedicatedWorkerGlobalScope, stores and cancels worker rAF callbacks on the worker global, and delivers callbacks through the worker event loop

Testing:
tests/wpt/tests/workers/WorkerGlobalScope_requestAnimationFrame.worker.js
tests/wpt/tests/workers/worker-request-animation-frame.html
tests/wpt/tests/html/dom/idlharness.any.js

@Taym95
Taym95 requested a review from gterzian as a code owner July 3, 2026 10:23
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Jul 3, 2026
@Taym95
Taym95 marked this pull request as draft July 3, 2026 10:23
@Taym95 Taym95 added the T-linux-wpt Do a try run of the WPT label Jul 3, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 3, 2026
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

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

@Taym95
Taym95 force-pushed the script-dedicated-worker-animation-frames branch from 4f9d58b to f936d54 Compare July 3, 2026 10:43
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

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

Flaky unexpected result (26)
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-00.html
    • NOTRUN [expected PASS] subtest: Overall test
  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-06.html
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-14.html
  • TIMEOUT /content-security-policy/inheritance/auxiliary-blank-document.html (#44821)
    • PASS [expected FAIL] subtest: For transient doc, violation event occurs in auxiliary, not opener window.
  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#45763)
  • PASS [expected FAIL] /css/css-text-decor/text-underline-position-from-font-variable.html (#45615)
  • TIMEOUT [expected OK] /fetch/content-encoding/br/big-br-body.https.any.worker.html
    • TIMEOUT [expected PASS] subtest: large br data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large br data should be decompressed successfully with byte stream
  • TIMEOUT [expected OK] /fetch/content-encoding/gzip/big-gzip-body.https.any.sharedworker.html
    • TIMEOUT [expected PASS] subtest: large gzip data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large gzip data should be decompressed successfully with byte stream
  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/009.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url with document.write and href navigation
  • 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 [expected TIMEOUT] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-requestsubmit.html (#44098)
    • FAIL [expected TIMEOUT] subtest: Replace before load, triggered by formElement.requestSubmit()

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement=" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20form%20%3D%20document.createElement(%22form%22)%3B%0A%20%20%20%20form.action%20%3D%20%22%2Fcommon%2Fblank.html%22%3B%0A%0A%20%20%20%20const%20input%20%3D%20document.createElement(%22input%22)%3B%0A%20%20%20%20input.type%20%3D%20%22hidden%22%3B%0A%20%20%20%20input.name%20%3D%20%22thereplacement%22%3B%0A%20%20%20%20form.append(input)%3B%0A%0A%20%20%20%20document.currentScript.before(form)%3B%0A%20%20%20%20form.requestSubmit()%3B%0A%20%20"
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • FAIL [expected TIMEOUT] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      assert_array_equals: animationFrame lengths differ, expected array ["autofocus", "scroll", "animationFrame"] length 3, got ["animationFrame"] length 1
      

  • OK /html/semantics/forms/form-submission-0/jsurl-form-submit.tentative.html (#36489)
    • PASS [expected FAIL] subtest: Verifies that form submissions scheduled inside javascript: urls take precedence over the javascript: url's return value.
  • CRASH [expected ERROR] /html/semantics/forms/the-select-element/customizable-select/select-appearance-button-after-span.html
  • OK /html/semantics/scripting-1/the-script-element/execution-timing/077.html (#22139)
    • PASS [expected FAIL] subtest: adding several types of scripts through the DOM and removing some of them confuses scheduler
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write.html?file=tests19
    • TIMEOUT [expected PASS] subtest: <!doctype html><math><mn DefinitionUrl="foo">

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><html></p><!--foo-->

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><head></head></p><!--foo-->

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><body><p><pre>

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><body><p><listing>

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><p><plaintext>

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><p><h1>

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <!doctype html><isindex type="hidden">

      Test timed out
      

    • NOTRUN [expected PASS] subtest: <!doctype html><ruby><p><rp>
    • NOTRUN [expected PASS] subtest: <!doctype html><ruby><div><span><rp>
    • And 93 more unexpected results...
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write_single.html?file=tests5
    • TIMEOUT [expected PASS] subtest: <style> <!-- </style>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <style> <!-- </style> --> </style>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <style> <!--> </style>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <style> <!---> </style>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <iframe> <!---> </iframe>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <iframe> <!--- </iframe>->x</iframe> --> </iframe>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <script> <!-- </script> --> </script>x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: <title> <!-- </title> --> </title>x

      Test timed out
      

    • NOTRUN [expected PASS] subtest: <textarea> <!--- </textarea>->x</textarea> --> </textarea>x
    • NOTRUN [expected PASS] subtest: <style> <!</-- </style>x
    • And 6 more unexpected results...
  • TIMEOUT [expected OK] /infrastructure/testdriver/click_nested.html (#43887)
    • NOTRUN [expected FAIL] subtest: TestDriver click method with multiple windows and nested iframe
  • TIMEOUT [expected OK] /pointerevents/compat/pointerevent_touch-action_two-finger_interaction.html (#44693)
    • NOTRUN [expected PASS] subtest: touch two-finger pan on 'touch-action: pan-x pan-y'
    • NOTRUN [expected FAIL] subtest: touch two-finger pan on 'touch-action: pinch-zoom'
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?01-05 (#38975)
    • PASS [expected TIMEOUT] subtest: Navigate a window via anchor with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via anchor with javascript:-urls in enforcing mode.
  • CRASH [expected OK] /uievents/mouse/mousemove_prevent_default_action.html
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • CRASH [expected OK] /webstorage/storage_local_setitem_quotaexceedederr.window.html
  • OK /webxr/xrSession_features_deviceSupport.https.html (#24357)
    • FAIL [expected PASS] subtest: Immersive XRSession requests with no supported device should reject

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

Stable unexpected results that are known to be intermittent (13)
  • OK /css/css-animations/animation-iteration-event-001.html (#46004)
    • PASS [expected FAIL] subtest: Got the expected elapsedTime in the correct order
  • 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 /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - Not sent to non-trustworthy same-origin destination

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - Not sent to non-trustworthy cross-site destination

      Test timed out
      

    • FAIL [expected PASS] subtest: content sec-fetch-site - HTTPS downgrade-upgrade

      assert_unreached: Reached unreachable code
      

  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-submit.html (#44028)
  • TIMEOUT [expected CRASH] /html/browsers/history/the-history-interface/001.html (#12580)
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • PASS [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "appendChild", w.document.querySelector(...) is null"
      

  • TIMEOUT /html/semantics/embedded-content/media-elements/preserves-pitch.html (#40352)
    • TIMEOUT [expected PASS] subtest: Speed-ups should not change the pitch when preservesPitch=true

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Slow-downs should not change the pitch when preservesPitch=true
    • NOTRUN [expected TIMEOUT] subtest: Speed-ups should change the pitch when preservesPitch=false
  • OK /mixed-content/tentative/autoupgrades/video-upgrade.https.sub.html (#41135)
    • FAIL [expected PASS] subtest: Video of other host autoupgraded

      assert_equals: Length. Other host expected 1 but got Infinity
      

  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?16-20 (#44835)
    • FAIL [expected PASS] subtest: Navigate a frame via area with javascript:-urls in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • TIMEOUT [expected PASS] subtest: Navigate a frame via area with javascript:-urls w/ default policy in report-only mode.

      Test timed out
      

  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • FAIL [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      assert_true: about:blank window opened by 3P iframe does not inherit 3P iframe's StorageKey expected true got false
      

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

✨ Try run (#28654422205) succeeded.

@gterzian gterzian left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure if we want the constellation to directly send a rednering oppirtunity to workers, because the concept of https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#concept-animationframeprovider-supported depends on https://html.spec.whatwg.org/multipage/workers.html#concept-WorkerGlobalScope-owner-set, which changes at https://html.spec.whatwg.org/multipage/document-lifecycle.html#destroying-documents:concept-WorkerGlobalScope-owner-set.

So maybe this can be managed by the constellation, since the constellation also is involved in unregistereing the worker as a receiver of rendering opportunities, but now this happens as part of https://html.spec.whatwg.org/multipage/workers.html#close-a-worker, which is not the same thing as when the spec removes the document from the owner set (although in Servo it might actually kind of the same thing, I haven't traced through it yet).

so I think the important part is, when a document is removed from the owner set, which is when it is destroyed in the spec, we should from then on stop delivering rendering opportunities to the worker, because it is not supported anymore from that point on.

This can be done by the constellation, but instead of happening only when the worker is closed, it should happen also when the owner set on which the "supported" concept relies(so in the case of nested workers it needs to go up the chain) becomes empty, so basically when the constellation has sent an exit message to a pipeline, it should remove that pipeline from the owner set, and then if it is empty stop sending rendering opportunities to workers who rely on that owner set to be supported.

So either way, you could make the script-thread responsible for forward rendering opportunities to supported workers, but this would require quite some changes, or you need to ensure this happens via teh constellation.

Comment thread components/script/dom/workers/workerglobalscope.rs
Comment thread components/constellation/constellation.rs Outdated

@gterzian gterzian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So to recap, we need to not just mark a worker as supported or not upon initialization, we need to track in some way what the owner set it, which can be done either by the script-thread(but that requires making it responsible for forwarding rednering opportunies to workers), or by the constellation (so pipelines are tracked as owners of workers, and nested workers rely on the owner set of the top most worker)

@mrobinson

Copy link
Copy Markdown
Member

So either way, you could make the script-thread responsible for forward rendering opportunities to supported workers, but this would require quite some changes, or you need to ensure this happens via teh constellation.

This may also be important because the compositor doesn't necessarily manage generating animation frames. When a page is requesting animation frames and nothing in the DOM is changing, generally the ScriptThread starts managing them on its own. I recommend digging in a bit to see how this mechanism works across all of Servo before writing this feature (as it quite complicated). You will need to design this very carefully.

@mrobinson

Copy link
Copy Markdown
Member

Another important question here: what should happen to workers and how they are managing animation frames when animation frame management moves from the ScriptThread to Paint and vice-versa. Both of these transitions can happen and this implementation needs to at least consider what happens during this transition.

@gterzian

gterzian commented Jul 22, 2026 •

Copy link
Copy Markdown
Member

I've had a look at what the script-thread does for rafs, and I now tend more towards the idea to handle the worker rafs from the constellation (or something at that level but living in the paint component) because:

  • what the document/script-thread does is complicated because of reflows and other things(see for example have_running_animations, while a worker only cares about: 1. whether it is supported and whether any rafs are present at the end of running update the rendering.
  • The worker update the rendering task is a simplified version of that of the window, see https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model:worker-event-loop-2 (reflecting the fact that the worker only cares about rafs, not all the other stuff)
  • Ideally it should be possible for a document to not reflow (and the script-thread to remain idle), but for only the embedded canvas to update via the worker (but not sure if that is feasible in Servo right now, although routing the working rendering op via the constellation or paint would be a step in that direction). Currently there is this FrameDelayer logic which might need an update to allow for only re-rendering a canvas without having received a new frame for the document itself (if that is possible at all).
  • Maybe this can be done in a way similar to what currently is done for the blinking caret over at WebContentAnimator, but applied to an offscreen canvas (so not re-rendering the containing document).

Also worth noting that this PR can focus on the delivery of a rendering opportunity to the worker, by queuing the update the rendering task, and the running of rafs, and the actually plugging into the painting can be done later as part of offscreen canvas (without it there is actually nothing to paint).

@Taym95

Taym95 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

So either way, you could make the script-thread responsible for forward rendering opportunities to supported workers, but this would require quite some changes, or you need to ensure this happens via teh constellation.

This may also be important because the compositor doesn't necessarily manage generating animation frames. When a page is requesting animation frames and nothing in the DOM is changing, generally the ScriptThread starts managing them on its own. I recommend digging in a bit to see how this mechanism works across all of Servo before writing this feature (as it quite complicated). You will need to design this very carefully.

window callbacks still use TickAllAnimations, while worker callbacks are merged into the same per-pipeline callback state that we send to Paint.
the worker path also explicitly requests another frame when it is still active after a tick but did not produce a display list, via GenerateFrame, so worker callbacks should keep running across the existing ScriptThread/Paint scheduling handoff.

@Taym95
Taym95 force-pushed the script-dedicated-worker-animation-frames branch from f936d54 to 5c1cc10 Compare July 22, 2026 15:24
@Taym95

Taym95 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

I've had a look at what the script-thread does for rafs, and I now tend more towards the idea to handle the worker rafs from the constellation (or something at that level but living in the paint component) because:

  • what the document/script-thread does is complicated because of reflows and other things(see for example have_running_animations, while a worker only cares about: 1. whether it is supported and whether any rafs are present at the end of running update the rendering.
  • The worker update the rendering task is a simplified version of that of the window, see https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model:worker-event-loop-2 (reflecting the fact that the worker only cares about rafs, not all the other stuff)
  • Ideally it should be possible for a document to not reflow (and the script-thread to remain idle), but for only the embedded canvas to update via the worker (but not sure if that is feasible in Servo right now, although routing the working rendering op via the constellation or paint would be a step in that direction). Currently there is this FrameDelayer logic which might need an update to allow for only re-rendering a canvas without having received a new frame for the document itself (if that is possible at all).
  • Maybe this can be done in a way similar to what currently is done for the blinking caret over at WebContentAnimator, but applied to an offscreen canvas (so not re-rendering the containing document).

Also worth noting that this PR can focus on the delivery of a rendering opportunity to the worker, by queuing the update the rendering task, and the running of rafs, and the actually plugging into the painting can be done later as part of offscreen canvas (without it there is actually nothing to paint).

Yes the current code already does that:

  • constellation tracks workers with active rAF callbacks.
  • It delivers a rendering opportunity directly to each active worker.
  • The worker event loop runs its rAF callbacks.
  • and paint is only used to keep refresh ticks coming.

@Taym95
Taym95 requested a review from gterzian July 22, 2026 15:25
@Taym95 Taym95 added the T-linux-wpt Do a try run of the WPT label Jul 22, 2026
@Taym95
Taym95 marked this pull request as ready for review July 22, 2026 15:26
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 22, 2026
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

⚠️ Try run (#29933340049) failed!

@Taym95
Taym95 force-pushed the script-dedicated-worker-animation-frames branch 2 times, most recently from c74b7c2 to fb7d201 Compare July 27, 2026 10:59
@Taym95 Taym95 added the T-linux-wpt Do a try run of the WPT label Jul 27, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 27, 2026
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

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

Flaky unexpected result (37)
  • CRASH [expected OK] /_mozilla/mozilla/focus-scroll-when-visible.html
  • CRASH [expected OK] /_webgl/conformance/glsl/misc/shader-with-glcolor.vert.html
  • TIMEOUT [expected OK] /_webgl/conformance/reading/read-pixels-test.html
  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-16.html
  • OK /cookies/partitioned-cookies/partitioned-cookies-samesite-attribute.https.html (#45255)
    • FAIL [expected PASS] subtest: In embedded cross-site contexts, partitioned cookies can only be set with explicit SameSite=None

      assert_equals: expected 0 but got 3
      

  • TIMEOUT [expected OK] /css/compositing/canvas-composite-modes.html
  • OK /css/css-animations/event-order.tentative.html (#39000)
    • PASS [expected FAIL] subtest: Same events on pseudo-elements follow the prescribed order
  • TIMEOUT [expected PASS] /css/css-flexbox/flexbox_flex-N-1-Npercent-shrink.html
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-weight: '430' should prefer '501 550' over '502 560'

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

  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#45763)
  • CRASH [expected OK] /dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html
  • TIMEOUT [expected OK] /fetch/content-encoding/br/big-br-body.https.any.html
    • TIMEOUT [expected PASS] subtest: large br data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large br data should be decompressed successfully with byte stream
  • TIMEOUT [expected OK] /fetch/content-encoding/br/big-br-body.https.any.worker.html
    • TIMEOUT [expected PASS] subtest: large br data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large br data should be decompressed successfully with byte stream
  • TIMEOUT [expected OK] /fetch/content-encoding/gzip/big-gzip-body.https.any.worker.html
    • TIMEOUT [expected PASS] subtest: large gzip data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large gzip data should be decompressed successfully with byte stream
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/sandboxed-iframe.https.window.html (#41704)
  • 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/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • OK [expected TIMEOUT] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-submit-button-click.html (#44099)
    • FAIL [expected TIMEOUT] subtest: Replace before load, triggered by submitButton.click()

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement=" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20form%20%3D%20document.createElement(%22form%22)%3B%0A%20%20%20%20form.action%20%3D%20%22%2Fcommon%2Fblank.html%22%3B%0A%0A%20%20%20%20const%20input%20%3D%20document.createElement(%22input%22)%3B%0A%20%20%20%20input.type%20%3D%20%22hidden%22%3B%0A%20%20%20%20input.name%20%3D%20%22thereplacement%22%3B%0A%20%20%20%20form.append(input)%3B%0A%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.type%20%3D%20%22submit%22%3B%0A%20%20%20%20form.append(button)%3B%0A%0A%20%20%20%20document.currentScript.before(form)%3B%0A%20%20%20%20button.click()%3B%0A%20%20"
      

  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • PASS [expected FAIL] subtest: traversing history must also traverse hash changes
  • CRASH [expected ERROR] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • OK /html/browsers/windows/embedded-opener-remove-frame.html (#23867)
    • PASS [expected FAIL] subtest: opener of discarded auxiliary browsing context
  • CRASH [expected OK] /html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-interface.html
  • OK [expected TIMEOUT] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-default-permissions-policy.https.sub.html (#46805)
    • PASS [expected TIMEOUT] subtest: Default "autoplay" feature policy ["self"] allows same-origin iframes.
  • TIMEOUT [expected OK] /html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html (#46789)
    • TIMEOUT [expected FAIL] subtest: TextTrack's activeCues are indexed and updated during video playback

      Test timed out
      

  • CRASH [expected ERROR] /html/semantics/forms/the-select-element/customizable-select/select-appearance-button-after-span.html
  • CRASH [expected FAIL] /html/semantics/interestfor/interestfor-plain-inline-element.tentative.html
  • OK /html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html (#44058)
    • PASS [expected FAIL] subtest: Parse errors in different files should be reported depending on different roots
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write_single.html?file=tests1 (#46327)
    • TIMEOUT [expected PASS] subtest: <!COM--MENT>

      Test timed out
      

  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html (#45151)
    • TIMEOUT [expected FAIL] subtest: Post-navigation state reset.

      Test timed out
      

  • OK /resize-observer/observer-in-cross-origin-frame.sub.html
    • FAIL [expected PASS] subtest: Cross-origin observer responds to explicitly set physical size

      assert_equals: expected 200 but got 284
      

  • OK /resource-timing/buffer-full-then-increased.html (#44408)
    • FAIL [expected PASS] subtest: Test that overflowing the buffer and immediately increasing its limit does not trigger the resourcetimingbufferfull event

      assert_equals: Number of entries does not match the expected value. expected 3 but got 1
      

  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?16-20 (#44835)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via area with javascript:-urls w/ default policy in enforcing mode.

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Navigate a frame via area with javascript:-urls in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via area with javascript:-urls w/ default policy in report-only mode.
  • TIMEOUT /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.
    • TIMEOUT [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.

      Test timed out
      

  • OK /uievents/order-of-events/mouse-events/mousemove-between.html
    • FAIL [expected PASS] subtest: Mousemove events between elements should fire in the correct order.

      assert_true: expected true got false
      

  • CRASH [expected OK] /upgrade-insecure-requests/gen/iframe-blank-inherit.meta/unset/worker-classic.https.html
  • CRASH [expected OK] /webstorage/storage_session_setitem_quotaexceedederr.window.html
Stable unexpected results that are known to be intermittent (17)
  • 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 /beacon/beacon-basic.https.window.html (#41723)
    • PASS [expected FAIL] subtest: Payload size restriction should be accumulated: type = blob
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.https.window.html (#35176)
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-dest - Not sent to non-trustworthy cross-site destination

      Test timed out
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • PASS [expected FAIL] subtest: Same-Document Referrer from Refresh
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • 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/supported-elements.html (#24145)
    • TIMEOUT [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-allowed-by-permissions-policy.https.sub.html (#46803)
    • TIMEOUT [expected PASS] subtest: Permissions-Policy header: autoplay * allows same-origin iframes.

      Test timed out
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/media-elements/autoplay-disabled-by-permissions-policy.https.sub.html (#46012, #46804)
    • TIMEOUT [expected PASS] subtest: Permissions-Policy header: autoplay "none" has no effect on the top level document.

      Test timed out
      

  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/src_object_blob.html (#40340)
    • PASS [expected TIMEOUT] subtest: HTMLMediaElement.srcObject blob
  • TIMEOUT /html/syntax/parsing/html5lib_write.html?file=processing-instructions (#46205)
    • TIMEOUT [expected FAIL] subtest: <body><?_prefix>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <body><?_prefix data>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <body><?_x132>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <body><?_x132 data>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <body><?_-_>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <head><?something>

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: <body><template><?something></template>

      Test timed out
      

  • OK /pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html (#46781)
    • FAIL [expected PASS] subtest: scroll was received while shouldn't

      assert_true: scroll received while shouldn't expected true got false
      

  • OK /pointerevents/pointerevent_pointercapture_in_frame.html?touch (#45445)
    • FAIL [expected PASS] subtest: Test touchpointer capture in same-origin frame: Pointer down at inner frame and set pointer capture.

      assert_true: Timed out waiting for lostpointercapture expected true got false
      

    • FAIL [expected PASS] subtest: Test touchpointer capture in same-origin frame: Pointer down at inner frame and set pointer capture to outer frame should not capture.

      assert_array_equals: Received events: innerFrame received pointerdown,innerFrame received pointermove,innerFrame received pointerup,innerFrame received lostpointercapture lengths differ, expected array ["innerFrame received pointerdown", "innerFrame received pointermove", "innerFrame received pointerup"] length 3, got ["innerFrame received pointerdown", "innerFrame received pointermove", "innerFrame received pointerup", "innerFrame received lostpointercapture"] length 4
      

  • OK /preload/prefetch-document.html (#37210)
    • FAIL [expected PASS] subtest: different-site document prefetch with 'as=document' should not be consumed

      assert_equals: expected 2 but got 1
      

  • OK /touch-events/hover-state-caused-by-compatibility-mouse-events.tentative.html (#46277)
    • PASS [expected FAIL] subtest: The compatibility mouse events should set :hover: The compatibility mouse events should be fired
    • PASS [expected FAIL] subtest: The compatibility mouse events should set :hover, but shouldn't be preserved after the target is replaced: The compatibility mouse events should be fired
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • PASS [expected TIMEOUT] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.

@github-actions

Copy link
Copy Markdown

✨ Try run (#30260288820) succeeded.

@gterzian gterzian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

couple of comments/questions

let animation_state = if callbacks_active {
AnimationState::AnimationCallbacksPresent
} else {
AnimationState::NoAnimationCallbacksPresent

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AnimationCallbacksAbsent

#[no_trace]
#[ignore_malloc_size_of = "channels are hard"]
animation_frame_tick_receiver: Option<RoutedReceiver<WorkerAnimationFrameTick>>,
/// A receiver of control messages.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit, it would be more readable with a spec between fields.

#[conditional_malloc_size_of]
closing: Arc<AtomicBool>,
#[conditional_malloc_size_of]
animation_frame_provider_supported: Arc<AtomicBool>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure we need this, because if the owning pipeline is closed the constellation will know about it, so it could stop sending rendering ops to the worker.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Huum, I think we need to keep it because the owner Doc can be destroyed before the pipeline exits, this flag disables rAF and clears the worker’s local callbacks other constellation only manages provider/tick tracking.

}

fn register_animation_frame_provider(&self) {
if !self.animation_frame_provider_supported() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

so this covers the case where the owner is closed even before the worker is started?

Not sure if that can ever be false, because starting a worker is called synchronously at

let join_handle = DedicatedWorkerGlobalScope::run_worker_scope(

@Taym95 Taym95 Aug 1, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

what if the owner document is be destroyed before the worker thread reaches register_animation_frame_provider() because run_worker_scope() starts the worker event loop asynchronously ?

Comment thread components/script/dom/workers/dedicatedworkerglobalscope.rs
AnimationState::NoAnimationCallbacksPresent => {
self.handle_change_document_animation_frame_provider_state(pipeline_id, false);
},
AnimationState::AnimationsPresent | AnimationState::NoAnimationsPresent => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

does this logic not logically cover the two above match arms as well, meaning we can remove the above two?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this need separate handler because AnimationsPresent and NoAnimationsPresent update the pipeline’s ordinary animation state, and callback states they update the document/worker callback bookkeeping.

cx,
);

global.register_animation_frame_provider();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should only be called once the first rafs have been requested for the worker scope.

@Taym95 Taym95 Aug 1, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

indeed to avoid registering inactive worker

debug!(
"Registering worker animation frame provider: worker={worker_id:?}, pipeline={pipeline_id:?}---->",
);
self.worker_animation_frame_providers.insert(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this might be ok for an initial pass, but this makes the workers animations dependent on that of the owning pipelines, so if the document itself isn't animating, we should probably send a PaintMessage::ChangeRunningAnimationsState here to make sure it does, although that could deliver rafs to a document that hasn't requested any. So ideally we should change the logic so that for a given pipeline (since that is what the painter tracks), we can opt to deliver rendering ops, but only for the actual global that requested it(so worker or documents, iframes?, independent of each other).

Right now I think delivering rendering ops to the worker is entirely dependent on the document animating (but I might be missing something).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Worker rAF is independent of document animation now, Paint still schedules at pipeline/WebView granularity, so finer per global scheduling can be handled separately.


/// <https://html.spec.whatwg.org/multipage/#event-loop-processing-model>
#[servo_tracing::instrument(skip_all)]
fn handle_tick_animation(&mut self, webview_ids: Vec<WebViewId>) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So this is entirely driven by documents having set the animating flag on the painter.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

callbacks_active is true when either:

pipeline.document_callbacks_active ||
!pipeline.worker_callbacks_active.is_empty()

pub document_callbacks_active: bool,

/// Workers in this pipeline with active animation frame callbacks.
pub worker_callbacks_active: FxHashSet<WorkerId>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure we need bot this and worker_animation_frame_providers, can we not consolidate in one place?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Combining them would mix provider lifetime/transport state with active callback state and complicate perpipeline scheduling.

@Taym95
Taym95 force-pushed the script-dedicated-worker-animation-frames branch from fb7d201 to d040999 Compare July 27, 2026 23:33
Taym95 added 4 commits July 31, 2026 19:07
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
@Taym95
Taym95 force-pushed the script-dedicated-worker-animation-frames branch from d040999 to 7587e7c Compare August 1, 2026 21:35
@Taym95
Taym95 requested a review from gterzian August 1, 2026 21:35
@Taym95 Taym95 added the T-linux-wpt Do a try run of the WPT label Aug 1, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

Flaky unexpected result (37)
  • OK /IndexedDB/idbtransaction-oncomplete.any.worker.html (#42804)
    • FAIL [expected PASS] subtest: IDBTransaction - complete event

      assert_array_equals: lengths differ, expected array ["upgradeneeded", "complete", "success", "opencursor"] length 4, got ["upgradeneeded", "complete", "success"] length 3
      

  • ERROR [expected OK] /_mozilla/mozilla/img-load-more-than-cache.html
  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-07.html
  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-14.html
  • TIMEOUT [expected OK] /_webgl/conformance2/query/occlusion-query.html
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /cookies/partitioned-cookies/partitioned-cookies-samesite-attribute.https.html (#45255)
    • FAIL [expected PASS] subtest: In embedded cross-site contexts, partitioned cookies can only be set with explicit SameSite=None

      assert_equals: expected 0 but got 3
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-inline/baseline-source/baseline-source-first-textarea-001.tentative.html
    • FAIL [expected PASS] subtest: .target &gt; * 1

      assert_equals: 
      &lt;span data-offset-y="29"&gt;&lt;/span&gt;
      offsetTop expected 29 but got 30
      

    • FAIL [expected PASS] subtest: .target &gt; * 3

      assert_equals: 
      &lt;span data-offset-y="29"&gt;&lt;/span&gt;
      offsetTop expected 29 but got 30
      

    • FAIL [expected PASS] subtest: .target &gt; * 5

      assert_equals: 
      &lt;span data-offset-y="29"&gt;&lt;/span&gt;
      offsetTop expected 29 but got 30
      

  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#45763)
  • FAIL [expected PASS] /css/css-text-decor/text-underline-position-from-font-variable.html (#45615)
  • CRASH [expected OK] /dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html
  • OK /dom/nodes/moveBefore/iframe-document-preserve.window.html (#43152)
    • FAIL [expected PASS] subtest: moveBefore(): cross-origin iframe is preserved: remove self via innerHTML

      assert_equals: iframe does not fire a second load event expected 1 but got 0
      

  • TIMEOUT [expected OK] /fetch/content-encoding/br/big-br-body.https.any.worker.html
    • TIMEOUT [expected PASS] subtest: large br data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large br data should be decompressed successfully with byte stream
  • TIMEOUT [expected OK] /fetch/content-encoding/zstd/big-zstd-body.https.any.worker.html
    • TIMEOUT [expected PASS] subtest: large zstd data should be decompressed successfully

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: large zstd data should be decompressed successfully with byte stream
  • TIMEOUT /fetch/metadata/generated/css-images.https.sub.tentative.html (#42229)
    • FAIL [expected PASS] subtest: content sec-fetch-site - Cross-Site -&gt; Cross-Site

      assert_unreached: 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/refresh/same-document-refresh.html (#34597)
    • PASS [expected FAIL] subtest: Same-Document Referrer from Refresh
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&amp;code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-submit.html (#44028)
  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • PASS [expected FAIL] subtest: traversing history must also traverse hash changes
  • CRASH [expected ERROR] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • TIMEOUT [expected FAIL] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      Test timed out
      

  • 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"
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigate_other_frame_popup.sub.html (#39702)
    • TIMEOUT [expected FAIL] subtest: Sandboxed iframe can not navigate other frame's popup

      Test timed out
      

  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html (#45151)
    • TIMEOUT [expected FAIL] subtest: Post-navigation state reset.

      Test timed out
      

  • OK [expected TIMEOUT] /infrastructure/testdriver/click_nested.html (#43887)
    • FAIL [expected NOTRUN] subtest: TestDriver click method with multiple windows and nested iframe

      can't access property "document", child.frames[2] is undefined
      

  • OK /mixed-content/tentative/autoupgrades/video-upgrade.https.sub.html (#41135)
    • FAIL [expected PASS] subtest: Video of other host autoupgraded

      assert_equals: Length. Other host expected 1 but got Infinity
      

  • TIMEOUT [expected OK] /pointerevents/compat/pointerevent_touch-action_two-finger_interaction.html (#44693)
    • NOTRUN [expected PASS] subtest: touch two-finger pan on 'touch-action: pan-x pan-y'
    • NOTRUN [expected FAIL] subtest: touch two-finger pan on 'touch-action: pinch-zoom'
  • CRASH [expected TIMEOUT] /referrer-policy/gen/req.attr/no-referrer/svg-a-tag.http.html
  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • PASS [expected FAIL] subtest: Click event should be fired when touchend opens synchronous XHR
  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?16-20 (#44835)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via area with javascript:-urls w/ default policy in enforcing mode.

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Navigate a frame via area with javascript:-urls in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via area with javascript:-urls w/ default policy in report-only mode.
  • TIMEOUT /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • PASS [expected TIMEOUT] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • TIMEOUT [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.

      Test timed out
      

  • CRASH [expected OK] /upgrade-insecure-requests/gen/iframe-blank-inherit.meta/unset/worker-import.https.html
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • TIMEOUT [expected OK] /webstorage/storage_local_setitem_quotaexceedederr.window.html
  • CRASH [expected OK] /webstorage/storage_session_setitem_quotaexceedederr.window.html
Stable unexpected results that are known to be intermittent (14)
  • OK /beacon/beacon-basic.https.window.html (#41723)
    • FAIL [expected PASS] subtest: Payload size restriction should be accumulated: type = string

      assert_false: expected false got true
      

  • ERROR [expected TIMEOUT] /html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html (#40387)
  • OK /html/browsers/windows/embedded-opener-remove-frame.html (#23867)
    • PASS [expected FAIL] subtest: opener of discarded auxiliary browsing context
  • OK [expected TIMEOUT] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • PASS [expected TIMEOUT] subtest: &lt;dialog&gt;-contained autofocus element gets focused when the dialog is shown
  • TIMEOUT [expected OK] /html/semantics/embedded-content/media-elements/autoplay-disabled-by-permissions-policy.https.sub.html (#46012, #46804)
    • TIMEOUT [expected PASS] subtest: Permissions-Policy header: autoplay "none" has no effect on the top level document.

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: Permissions-Policy header: autoplay "none" disallows same-origin iframes.

      Test timed out
      

  • OK /html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html (#44058)
    • PASS [expected FAIL] subtest: Parse errors in different files should be reported depending on different roots
  • OK [expected TIMEOUT] /html/syntax/parsing/html5lib_write.html?file=processing-instructions (#46205)
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write_single.html?file=processing-instructions (#46206)
    • TIMEOUT [expected FAIL] subtest: &lt;div&gt;&lt;?something good&gt;&lt;/div&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;table&gt;&lt;?something&gt;&lt;/table&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;table&gt;&lt;tr&gt;&lt;?something&gt;&lt;/tr&gt;&lt;/table&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;script&gt;&lt;?something&gt;&lt;/script&gt;

      Test timed out
      

  • OK /pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html (#46781)
    • FAIL [expected PASS] subtest: scroll was received while shouldn't

      assert_true: scroll received while shouldn't expected true got false
      

  • OK /preload/prefetch-document.html (#37210)
    • FAIL [expected PASS] subtest: different-site document prefetch with 'as=document' should not be consumed

      assert_equals: expected 2 but got 1
      

  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • FAIL [expected PASS] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one

      assert_equals: Number of entries does not match the expected value. expected 3 but got 0
      

  • OK /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • FAIL [expected PASS] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • PASS [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

✨ Try run (#30719468994) succeeded.

@gterzian gterzian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what if during worker or pipeline teardown a missing provider can occur? we would just skip it no?

Yes but we can log an error.

Otherwise looks good to me as a first step towards enabling off thread canvas.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Aug 3, 2026
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Aug 6, 2026
@Taym95
Taym95 enabled auto-merge August 6, 2026 09:02
@Taym95
Taym95 added this pull request to the merge queue Aug 6, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Aug 6, 2026
Merged via the queue into servo:main with commit 12c1908 Aug 6, 2026
36 checks passed
@Taym95
Taym95 deleted the script-dedicated-worker-animation-frames branch August 6, 2026 11:48
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Aug 6, 2026
RichardTjokroutomo pushed a commit to RichardTjokroutomo/servo that referenced this pull request Oct 6, 2026
this exposess AnimationFrameProvider on DedicatedWorkerGlobalScope,
stores and cancels worker rAF callbacks on the worker global, and
delivers callbacks through the worker event loop

Testing: 

tests/wpt/tests/workers/WorkerGlobalScope_requestAnimationFrame.worker.js
tests/wpt/tests/workers/worker-request-animation-frame.html 
tests/wpt/tests/html/dom/idlharness.any.js

---------

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-awaiting-review There is new code that needs to be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants