Skip to content

script: Notify embedder coalesced events to resolve potential WebDriver deadlock#43202

Merged
yezhizhen merged 4 commits intoservo:mainfrom
yezhizhen:feedback-to-coalesced
Mar 12, 2026
Merged

script: Notify embedder coalesced events to resolve potential WebDriver deadlock#43202
yezhizhen merged 4 commits intoservo:mainfrom
yezhizhen:feedback-to-coalesced

Conversation

@yezhizhen
Copy link
Copy Markdown
Member

@yezhizhen yezhizhen commented Mar 12, 2026

Notify embedder the coalesced wheel/mousemove event.

We also stop cloning every single entry in pending_input_event.

Testing: This should unblock the potential WebDriver thread deadlock
when receiving simultaneous wheel or pointer inputs from multiple sources.
We added a new test that stably deadlock on 74c16ff.
Firefox/Safari/Chrome all pass the new test.
Fixes: #43136 (comment)

@yezhizhen yezhizhen requested a review from xiaochengh March 12, 2026 04:54
@yezhizhen yezhizhen requested a review from gterzian as a code owner March 12, 2026 04:54
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 12, 2026
@yezhizhen yezhizhen added the T-linux-wpt Do a try run of the WPT label Mar 12, 2026
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Mar 12, 2026
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (21)
  • CRASH [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • CRASH [expected OK] /_webgl/conformance/extensions/oes-texture-half-float-with-image.html
  • OK /beacon/beacon-basic.https.window.html (#41723)
    • FAIL [expected PASS] subtest: Payload size restriction should be accumulated: type = arraybuffer

      assert_false: expected false got true
      

  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • PASS [expected FAIL] subtest: Delete layer invalidates @font-face
  • OK /css/css-fonts/generic-family-keywords-002.html (#40929)
    • FAIL [expected PASS] subtest: font-family: -webkit-serif treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-sans-serif treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-cursive treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-fantasy treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-monospace treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-system-ui treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-math treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • PASS [expected FAIL] subtest: font-family: -webkit-generic(fangsong) treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(kai) treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(khmer-mul) treated as <font-family>, not <generic-name>
    • And 12 more unexpected results...
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-mode
  • 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-fragment.html (#20768)
    • FAIL [expected PASS] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation

      assert_equals: expected "" but got "#fragment"
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_2.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 3 but got 2 (expected array [6, 3] got [6, 2])
      

  • CRASH [expected OK] /html/browsers/sandboxing/sandbox-initial-empty-document-toward-same-origin.html (#35948)
  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • PASS [expected FAIL] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due
  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html (#39703)
    • FAIL [expected PASS] subtest: Meta refresh of the original iframe is not blocked if moved into a sandboxed iframe

      uncaught exception: Error: assert_unreached: The iframe into which the meta was moved must not refresh Reached unreachable code
      

  • 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
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • OK /html/webappapis/dynamic-markup-insertion/document-write/module-tla-import.html (#42419)
    • FAIL [expected PASS] subtest: document.write in an imported module

      assert_true: onload must be called expected true got false
      

  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • OK /wasm/webapi/abort.any.html (#39966)
    • FAIL [expected PASS] subtest: compileStreaming() asynchronously racing with abort should succeed or reject with AbortError

      assert_equals: expected "AbortError" but got "CompileError"
      

  • CRASH [expected OK] /webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/closed-audiocontext-construction.html
  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe
  • 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
      

  • OK /xhr/send-redirect.htm (#32026)
    • FAIL [expected PASS] subtest: XMLHttpRequest: send() - Redirects (basics) (302, GET, content.py)

      assert_equals: expected (string) "GET" but got (object) null
      

Stable unexpected results that are known to be intermittent (15)
  • 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 /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: Blob URL store error: InvalidFileID"
      

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

  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(kai)

      assert_equals: quoted generic(kai) matches  @font-face rule expected 50 but got 30
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted cursive (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted monospace (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted system-ui (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(khmer-mul) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-serif (drawing text in a canvas)
  • OK [expected TIMEOUT] /html/anonymous-iframe/indexeddb.tentative.https.window.html (#39254)
    • FAIL [expected TIMEOUT] subtest: indexeddb

      assert_equals: expected (undefined) undefined but got (string) "ef3fff34-7b29-4496-a774-e9a9ec31ac1a"
      

  • 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/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 5 but got 3 (expected array [6, 5] got [6, 3])
      

  • TIMEOUT /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 TIMEOUT] subtest: Host element with delegatesFocus should support autofocus
  • TIMEOUT /html/semantics/embedded-content/media-elements/preserves-pitch.html (#40352)
    • PASS [expected TIMEOUT] subtest: Speed-ups should not change the pitch when preservesPitch=true
    • PASS [expected NOTRUN] subtest: Slow-downs should not change the pitch when preservesPitch=true
    • TIMEOUT [expected NOTRUN] subtest: Speed-ups should change the pitch when preservesPitch=false

      Test timed out
      

  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • FAIL [expected PASS] subtest: Reload domComplete > Original domComplete

      assert_true: Reload domComplete > Original domComplete expected true got false
      

    • FAIL [expected PASS] subtest: Reload domInteractive > Original domInteractive

      assert_true: Reload domInteractive > Original domInteractive expected true got false
      

    • FAIL [expected PASS] subtest: Reload fetchStart > Original fetchStart

      assert_true: Reload fetchStart > Original fetchStart expected true got false
      

    • FAIL [expected PASS] subtest: Reload loadEventEnd > Original loadEventEnd

      assert_true: Reload loadEventEnd > Original loadEventEnd expected true got false
      

    • FAIL [expected PASS] subtest: Reload loadEventStart > Original loadEventStart

      assert_true: Reload loadEventStart > Original loadEventStart expected true got false
      

  • 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 /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: buffer-stitching-1

      assert_approx_equals: Stitched sine‑wave buffers at sample rate 44100 sample[16770] |2.8768211046036067e-24 - 0.9055536389350891| = 0.9055536389350891 > 0.000090957 expected 0.9055536389350891 +/- 0.000090957 but got 2.8768211046036067e-24
      

@github-actions
Copy link
Copy Markdown

✨ Try run (#22987221590) succeeded.

@yezhizhen
Copy link
Copy Markdown
Member Author

Testing: ?. This should unblock the potential WebDriver thread deadlock,
when we have two sources of wheel/pointer input.

We can add a test for this that stably deadlocks.

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

🤖 Opened new upstream WPT pull request (web-platform-tests/wpt#58445) with upstreamable changes.

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#58445) title and body.

@yezhizhen yezhizhen force-pushed the feedback-to-coalesced branch from a419db4 to 2b8a008 Compare March 12, 2026 07:46
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58445).

@yezhizhen yezhizhen requested a review from mrobinson March 12, 2026 09:17
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58445).

@yezhizhen yezhizhen force-pushed the feedback-to-coalesced branch from 0c34f92 to ba5b4a6 Compare March 12, 2026 09:39
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58445).

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#58445) title and body.

@yezhizhen yezhizhen force-pushed the feedback-to-coalesced branch from ba5b4a6 to f729e2e Compare March 12, 2026 10:27
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58445).

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#58445) title and body.

coalesced_move_event_ids: DomRefCell<Vec<InputEventId>>,
/// The index of the last wheel event in the pending input events queue.
/// This is non-standard behaviour.
/// According to <https://www.w3.org/TR/pointerevents/#dfn-coalesced-events>,
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.

Oh, I had no idea this was in the specification. I guess we are going to have to expose these events somehow.

Copy link
Copy Markdown
Member Author

@yezhizhen yezhizhen Mar 12, 2026

Choose a reason for hiding this comment

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

Yeah. These are supposed to be a list of PointerEvents, accessed through getCoalescedEvents() in the fired PointerEvent.
We need to store extra events tho.

Personally, I hope we don't rush this for performance consideration :|

Copy link
Copy Markdown
Member Author

@yezhizhen yezhizhen Mar 12, 2026

Choose a reason for hiding this comment

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

I guess it is needed for things like shooting game/drawing.. Which should not be our current concern.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Mar 12, 2026
@yezhizhen yezhizhen added this pull request to the merge queue Mar 12, 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 Mar 12, 2026
@yezhizhen yezhizhen removed this pull request from the merge queue due to a manual request Mar 12, 2026
@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 Mar 12, 2026
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 12, 2026
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58445).

@yezhizhen yezhizhen enabled auto-merge March 12, 2026 12:39
@yezhizhen yezhizhen added this pull request to the merge queue Mar 12, 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 Mar 12, 2026
Merged via the queue into servo:main with commit e88c5dd Mar 12, 2026
33 checks passed
@yezhizhen yezhizhen deleted the feedback-to-coalesced branch March 12, 2026 14:07
@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 Mar 12, 2026
github-merge-queue bot pushed a commit that referenced this pull request Mar 13, 2026
This is a hot path. This way we free the unused memory earlier.
Didn't realize the difference in #43202.

Testing: This is a memory optimization that does not change visible
behaviour.

Signed-off-by: Euclid Ye <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Mar 14, 2026
…43262)

This is now possible since #43202. We remove the workaround introduced
long ago.

Testing: Before #43202, this would deadlock in many tests, and is
therefore covered by existing tests.
[Try](https://github.com/servo/servo/actions/runs/23080857516)

---------

Signed-off-by: Euclid Ye <[email protected]>
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.

Need to replace input_id when coalescing existing input event to unblock the thread

4 participants