Skip to content

layout: Prevent DomRefCell::borrow from being used in layout code#42976

Merged
jdm merged 4 commits into
servo:mainfrom
jdm:thread-checks
Mar 4, 2026
Merged

layout: Prevent DomRefCell::borrow from being used in layout code#42976
jdm merged 4 commits into
servo:mainfrom
jdm:thread-checks

Conversation

@jdm
Copy link
Copy Markdown
Member

@jdm jdm commented Mar 3, 2026

DomRefCell::borrow inside of layout code is risky because it leads to memory races if the code is ever called from layout worker threads. This can be caught via TSAN, but we can also catch it deterministically in CI by using our existing thread state debug assertions correctly.

Testing: Existing WPT test coverage is sufficient.
Fixes: #42962

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 3, 2026
@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 3, 2026

@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 3, 2026

I recommend reading this PR with whitespace changes turned off.

@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 3, 2026

We could catch problems like #42963 as well by introducing a similar DomCell type.

Copy link
Copy Markdown
Member

@mukilan mukilan left a comment

Choose a reason for hiding this comment

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

Nice!

Comment thread components/script/dom/bindings/cell.rs
Comment thread components/layout/layout_impl.rs
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Mar 3, 2026
Comment thread components/layout/layout_impl.rs
fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
self.unsafe_get().implemented_pseudo_element()
unsafe {
self.unsafe_get()
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.

Unrelated to this PR, but why is unsafe_get a safe function?

Copy link
Copy Markdown
Member Author

@jdm jdm Mar 3, 2026

Choose a reason for hiding this comment

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

I don't have a good answer for why the unsafe is in the name instead of in the type system. I think we could potentially rename it to something more clear, but it's meant to represent that it should only be called by code that is implementing the LayoutWhateverHelpers traits, since it exposes methods that could be unsafe to call in layout's worker threads.

Signed-off-by: Josh Matthews <[email protected]>
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 3, 2026
@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 3, 2026

@simonwuelker Do you have a preference for merging this change or #42991 first?

@simonwuelker
Copy link
Copy Markdown
Member

Let's merge this one first.

@jdm jdm added this pull request to the merge queue Mar 3, 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 3, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Mar 3, 2026
@servo-highfive servo-highfive added S-tests-failed The changes caused existing tests to fail. and removed S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. labels Mar 3, 2026
@jdm jdm added this pull request to the merge queue Mar 3, 2026
@servo-highfive servo-highfive added S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. and removed S-tests-failed The changes caused existing tests to fail. labels Mar 3, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Mar 3, 2026
@servo-highfive servo-highfive added S-tests-failed The changes caused existing tests to fail. and removed S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. labels Mar 3, 2026
@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 4, 2026

Womp womp!

  │ assertion failed: thread_state::get().is_script() (thread StyleThread#1, at components/script_bindings/root.rs:450)
  │    0: servoshell::backtrace::print
  │    1: servoshell::panic_hook::panic_hook
  │    2: std::panicking::panic_with_hook
  │    3: std::panicking::panic_handler::{{closure}}
  │    4: std::sys::backtrace::__rust_end_short_backtrace
  │    5: __rustc::rust_begin_unwind
  │    6: core::panicking::panic_fmt
  │    7: core::panicking::panic
  │    8: script_bindings::root::assert_in_script
  │    9: <script::dom::bindings::root::LayoutDom<script::dom::element::Element> as script::dom::element::LayoutElementHelpers>::each_custom_state_for_layout
  │   10: <script::layout_dom::element::ServoLayoutElement as selectors::tree::Element>::match_non_ts_pseudo_class
  │   11: selectors::matching::matches_simple_selector
  │   12: selectors::matching::matches_complex_selector_internal
  │   13: style::selector_map::SelectorMap<style::stylist::Rule>::get_matching_rules
  │   14: style::selector_map::SelectorMap<style::stylist::Rule>::get_all_matching_rules
  │   15: style::rule_collector::RuleCollector<E>::collect_stylist_rules
  │   16: style::rule_collector::RuleCollector<E>::collect_all
  │   17: style::stylist::Stylist::push_applicable_declarations
  │   18: style::style_resolver::StyleResolverForElement<E>::match_primary
  │   19: style::style_resolver::StyleResolverForElement<E>::resolve_primary_style
  │   20: style::style_resolver::StyleResolverForElement<E>::resolve_style
  │   21: style::style_resolver::StyleResolverForElement<E>::resolve_style_with_default_parents
  │   22: style::traversal::compute_style
  │   23: <layout::traversal::RecalcStyle as style::traversal::DomTraversal<E>>::process_preorder
  │   24: style::parallel::style_trees
  │   25: style::driver::traverse_dom::{{closure}}
  │   26: rayon_core::scope::ScopeBase::execute_job_closure
  │   27: <rayon_core::job::HeapJob<BODY> as rayon_core::job::Job>::execute
  │   28: rayon_core::registry::WorkerThread::wait_until_cold
  │   29: rayon_core::registry::ThreadBuilder::run
  │   30: std::sys::backtrace::__rust_begin_short_backtrace
  │   31: core::ops::function::FnOnce::call_once{{vtable.shim}}
  │   32: std::sys::thread::unix::Thread::new::thread_start
  │   33: <unknown>
  └   34: <unknown>

fn each_custom_state_for_layout(self, mut callback: impl FnMut(&AtomIdent)) {
let rare_data = self.unsafe_get().rare_data();

fn rare_data(&self) -> Ref<'_, Option<Box<ElementRareData>>> {
self.rare_data.borrow()
}

@jdm
Copy link
Copy Markdown
Member Author

jdm commented Mar 4, 2026

 │ assertion failed: thread_state::get().is_script() (thread StyleThread#1, at components/script_bindings/root.rs:450)
  │    0: servoshell::backtrace::print
  │    1: servoshell::panic_hook::panic_hook
  │    2: std::panicking::panic_with_hook
  │    3: std::panicking::panic_handler::{{closure}}
  │    4: std::sys::backtrace::__rust_end_short_backtrace
  │    5: __rustc::rust_begin_unwind
  │    6: core::panicking::panic_fmt
  │    7: core::panicking::panic
  │    8: script_bindings::root::assert_in_script
  │    9: <script::layout_dom::element::ServoLayoutElement as selectors::tree::Element>::has_custom_state
  │   10: selectors::matching::matches_simple_selector
  │   11: selectors::matching::matches_complex_selector_internal
  │   12: style::selector_map::SelectorMap<style::stylist::Rule>::get_matching_rules
  │   13: style::selector_map::SelectorMap<style::stylist::Rule>::get_all_matching_rules
  │   14: style::rule_collector::RuleCollector<E>::collect_stylist_rules
  │   15: style::rule_collector::RuleCollector<E>::collect_all
  │   16: style::stylist::Stylist::push_applicable_declarations
  │   17: style::style_resolver::StyleResolverForElement<E>::match_primary
  │   18: style::style_resolver::StyleResolverForElement<E>::resolve_primary_style
  │   19: style::style_resolver::StyleResolverForElement<E>::resolve_style
  │   20: style::style_resolver::StyleResolverForElement<E>::resolve_style_with_default_parents
  │   21: style::traversal::compute_style
  │   22: style::parallel::style_trees
  │   23: style::driver::traverse_dom::{{closure}}
  │   24: <rayon_core::job::HeapJob<BODY> as rayon_core::job::Job>::execute
  │   25: rayon_core::registry::WorkerThread::wait_until_cold
  │   26: rayon_core::registry::ThreadBuilder::run
  │   27: std::sys::backtrace::__rust_begin_short_backtrace
  │   28: core::ops::function::FnOnce::call_once{{vtable.shim}}
  │   29: std::sys::thread::unix::Thread::new::thread_start
  │   30: <unknown>
  └   31: <unknown>

fn has_custom_state(&self, name: &AtomIdent) -> bool {
let mut has_state = false;
self.each_custom_state(|state| has_state |= state == name);

We need to call self.each_custom_state_for_layout from that code instead.

@servo-highfive servo-highfive removed the S-tests-failed The changes caused existing tests to fail. label Mar 4, 2026
@jdm jdm added the T-linux-wpt Do a try run of the WPT label Mar 4, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

⚠️ Try run (#22654988697) failed!

@jdm jdm force-pushed the thread-checks branch from 5a4ffdd to 3a54462 Compare March 4, 2026 04:36
@jdm jdm added the T-linux-wpt Do a try run of the WPT label Mar 4, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

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

Flaky unexpected result (30)
  • OK [expected TIMEOUT] /IndexedDB/idbfactory_open.any.worker.html
    • PASS [expected FAIL] subtest: Calling open() with version argument 1.5 should not throw.
    • PASS [expected TIMEOUT] subtest: Calling open() with version argument 9007199254740991 should not throw.
    • PASS [expected TIMEOUT] subtest: Calling open() with version argument undefined should not throw.
  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • CRASH [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • CRASH [expected OK] /_webgl/conformance/glsl/bugs/floored-division-accuracy.html
  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • PASS [expected FAIL] subtest: WebGL test #85
    • PASS [expected FAIL] subtest: WebGL test #87
    • PASS [expected FAIL] subtest: WebGL test #89
    • PASS [expected FAIL] subtest: WebGL test #91
    • FAIL [expected PASS] subtest: WebGL test #93

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #95

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #97

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #99

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

  • OK /css/css-animations/event-order.tentative.html (#39000)
    • PASS [expected FAIL] subtest: Same events on pseudo-elements follow the prescribed order
  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 1

      assert_equals: expected "80px" but got "38.3166666666667px"
      

    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 2

      assert_equals: expected "80px" but got "38.3166666666667px"
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted fantasy (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 math (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 generic(nastaliq) (drawing text in a canvas)
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-style: 'oblique -21deg' should prefer 'oblique -21deg' over 'oblique -60deg -40deg'

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

  • TIMEOUT [expected OK] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • TIMEOUT [expected PASS] subtest: [keepalive][iframe][load] mixed content redirect; setting up

      Test timed out
      

  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/sandboxed-iframe.https.window.html (#41704)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-user
  • TIMEOUT /fetch/metadata/generated/css-images.https.sub.tentative.html (#42229)
    • FAIL [expected PASS] subtest: content sec-fetch-site - Cross-Site -&gt; Same-Site

      assert_unreached: Reached unreachable code
      

    • 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-fragment.html (#20768)
    • PASS [expected FAIL] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • FAIL [expected TIMEOUT] subtest: &lt;dialog&gt;-contained autofocus element gets focused when the dialog is shown

      assert_equals: expected "DIV" but got "BODY"
      

  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html (#41404)
    • PASS [expected TIMEOUT] subtest: Feature-Policy header: autoplay * allows same-origin iframes.
  • 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
    • TIMEOUT [expected NOTRUN] subtest: Slow-downs should not change the pitch when preservesPitch=true

      Test timed out
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/media-elements/src_object_blob.html (#40340)
    • TIMEOUT [expected PASS] subtest: HTMLMediaElement.srcObject blob

      Test timed out
      

  • 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
      

  • 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.
  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • 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 [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.
  • 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!\""
      

  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • CRASH [expected OK] /webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/closed-audiocontext-construction.html
  • OK /webdriver/tests/classic/delete_session/delete.py
    • FAIL [expected PASS] subtest: test_accepted_beforeunload_prompt

      webdriver.error.NoSuchWindowException: no such window (404): No such window
      

  • OK /webdriver/tests/classic/perform_actions/pointer_pause_dblclick.py
    • FAIL [expected PASS] subtest: test_dblclick_with_pause_after_second_pointerdown

      webdriver.error.NoSuchWindowException: no such window (404): No such window
      

  • OK /webdriver/tests/classic/take_screenshot/iframe.py
    • ERROR [expected PASS] subtest: test_always_captures_top_browsing_context

      setup error: ConnectionRefusedError: [Errno 111] Connection refused
      

    • ERROR [expected PASS] subtest: test_source_origin[same_origin]

      setup error: ConnectionRefusedError: [Errno 111] Connection refused
      

    • ERROR [expected PASS] subtest: test_source_origin[cross_origin]

      setup error: ConnectionRefusedError: [Errno 111] Connection refused
      

Stable unexpected results that are known to be intermittent (19)
  • OK /IndexedDB/transaction-scheduling-mixed-scopes.any.html (#42753)
    • PASS [expected FAIL] subtest: Check that scope restrictions on mixed transactions are enforced.
  • 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
      

  • ERROR [expected CRASH] /_webgl/conformance2/misc/uninitialized-test-2.html (#41656)
  • OK /beacon/beacon-basic.https.window.html (#41723)
    • PASS [expected FAIL] subtest: Payload size restriction should be accumulated: type = string
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)

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

  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • FAIL [expected PASS] subtest: content sec-fetch-dest - Not sent to non-trustworthy same-site destination

      assert_unreached: Reached unreachable code
      

  • OK [expected ERROR] /fetch/metadata/window-open.https.sub.html (#40339)
  • ERROR [expected TIMEOUT] /html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html (#40387)
  • 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/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)
    • 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"
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_3.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])
      

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

      assert_equals: expected Element node &lt;div autofocus=""&gt;&lt;/div&gt; but got Element node &lt;body&gt;&lt;div autofocus=""&gt;&lt;/div&gt;&lt;/body&gt;
      

    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      assert_equals: expected Element node &lt;input autofocus=""&gt;&lt;/input&gt; but got Element node &lt;body&gt;&lt;div autofocus=""&gt;&lt;/div&gt;&lt;input autofocus=""&gt;&lt;/body&gt;
      

    • 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/autoplay-default-feature-policy.https.sub.html (#41193)
    • PASS [expected TIMEOUT] subtest: Default "autoplay" feature policy ["self"] allows same-origin iframes.
  • 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
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete &gt; Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart &gt; Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd &gt; Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart &gt; Original loadEventStart
  • 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 /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.

      Test timed out
      

Stable unexpected results (1)
  • FAIL [expected PASS] /_mozilla/css/img_size_a.html

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

⚠️ Try run (#22655281627) failed!

@jdm jdm force-pushed the thread-checks branch from 3a54462 to 52f9571 Compare March 4, 2026 06:09
@jdm jdm enabled auto-merge March 4, 2026 06:12
@jdm jdm added this pull request to the merge queue Mar 4, 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 4, 2026
Merged via the queue into servo:main with commit f206571 Mar 4, 2026
30 checks passed
@jdm jdm deleted the thread-checks branch March 4, 2026 08:29
@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 4, 2026
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.

TSAN: data race between DomRefCell::borrow_for_layout and Node::implemented_pseudo_element

5 participants