Skip to content

layout: Use the Stylist to get list of @font-face rules - #46271

Merged
simonwuelker merged 5 commits into
servo:mainfrom
simonwuelker:stylist-font-face-rules
Jul 9, 2026
Merged

simonwuelker merged 5 commits into
servo:mainfrom
simonwuelker:stylist-font-face-rules

Conversation

@simonwuelker

@simonwuelker simonwuelker commented Jul 4, 2026

Copy link
Copy Markdown
Member

Instead of processing every font face rule as stylesheets are modified, process
all rules, properly cascaded by Stylo, right before layout. This fixes an issues with
flakiness around font loading and layers and avoids searching the stylesheet for
font face rules in O(n).

Fixes: #45975
Fixes: #36094.
Fixes: #35935.

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Jul 4, 2026
Comment on lines +1 to +3
[font-face-007.html]
[@font-face from shadow applies to :host]
expected: FAIL

@simonwuelker simonwuelker Jul 4, 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.

All major browsers besides safari fail these three tests because they don't implement tree scoped names. Now we do too, for the same reason.

The fact that we passed them before was just luck, because we didn't restrict @font-face rules to their shadow root at all.

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 the reason we are failing these now is that stylesheet rules inside of shadow roots are not included in the call to iter_extra_data_origins(), so there is a real regression here as previously shadow root-level stylesheets were completely mixed with document-level ones. I think that's an acceptable regression until we properly integrate them into the cascade (either scoped to their shadow roots or not -- as only WebKit seems to do this properly).

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.

I think the reason we are failing these now is that stylesheet rules inside of shadow roots are not included in the call to iter_extra_data_origins()

Yes, each shadow root has a AuthorStyles with its own CascadeData, seperate from the one the Stylist holds.

@simonwuelker
simonwuelker force-pushed the stylist-font-face-rules branch from bd28786 to 6cfca54 Compare July 4, 2026 21:53
@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Jul 4, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 4, 2026
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

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

Flaky unexpected result (40)
  • CRASH [expected OK] /_mozilla/mozilla/node-replaceChild.html
  • OK [expected TIMEOUT] /_webgl/conformance/textures/misc/tex-video-using-tex-unit-non-zero.html (#39735)
    • PASS [expected NOTRUN] subtest: Overall test
    • PASS [expected FAIL] subtest: WebGL test #0
  • TIMEOUT [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
    • NOTRUN [expected PASS] subtest: Overall test
  • CRASH [expected OK] /_webgl/conformance2/buffers/delete-buffer.html
  • TIMEOUT [expected OK] /_webgl/conformance2/sync/sync-webgl-specific.html
  • CRASH [expected OK] /_webgl/conformance2/transform_feedback/transform_feedback.html
  • 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
      

  • 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.
  • TIMEOUT [expected OK] /cookies/attributes/domain.sub.html
    • TIMEOUT [expected PASS] subtest: No host cookies returned for host cookies after non-host redirect 3

      Test timed out
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • FAIL [expected PASS] /css/css-fonts/font-feature-settings-descriptor-01.html (#45418)
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-weight: '399' should prefer '200 300' over '400'

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

    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 10deg' should prefer 'oblique -40deg -30deg' over 'italic'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique 40deg 50deg' over 'italic'
  • 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.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/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
  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • FAIL [expected PASS] subtest: content sec-fetch-site - HTTPS downgrade-upgrade

      assert_unreached: Reached unreachable code
      

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

  • CRASH [expected ERROR] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/src_object_blob.html (#40340)
    • PASS [expected TIMEOUT] subtest: HTMLMediaElement.srcObject blob
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-reload-location-reload.html (#32595)
    • FAIL [expected PASS] subtest: Reloading iframe loading='lazy' before it is loaded: location.reload

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

  • CRASH [expected 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)
    • FAIL [expected PASS] subtest: Parse errors in different files should be reported depending on different roots

      assert_not_equals: two different parse errors should be reported got disallowed value object "SyntaxError: expected expression, got '%'"
      

  • TIMEOUT [expected OK] /html/user-activation/propagation-sameorigin.html
    • NOTRUN [expected PASS] subtest: Propagation test
  • OK /paint-timing/with-lcp/fcp-document-opacity-image.html (#43068)
    • FAIL [expected PASS] subtest: Test that FCP after opacity change is not a larger value than LCP

      assert_equals: First contentful paint marked too early.  expected 0 but got 1
      

  • OK /pointerevents/compat/pointerevent_touch_target_after_pointerdown_target_removed.tentative.html (#42813)
    • FAIL [expected PASS] subtest: After a pointerdown listener removes its target, touch events should be fired on the touchstart target even though an orphan and pointer events should be fired on the parent

      assert_equals: expected "[ { type: pointerdown, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: touchstart, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchend, target: Element node <div id=\"pointerDownTarget\"></div> } ]" but got "[ { type: pointerdown, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: touchstart, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchend, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerdown, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> } ]"
      

    • FAIL [expected PASS] subtest: After a pointerdown listener removes its target, touchmove event should be fired on the pointerdown target

      assert_equals: expected "[ { type: pointerdown, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: touchstart, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchmove, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchend, target: Element node <div id=\"pointerDownTarget\"></div> } ]" but got "[ { type: pointerdown, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: touchstart, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchmove, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: touchend, target: Element node <div id=\"pointerDownTarget\"></div> }, { type: pointermove, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerdown, target: Element node <div id=\"pointerDownTargetParent\"></div> }, { type: pointerup, target: Element node <div id=\"pointerDownTargetParent\"></div> } ]"
      

    • PASS [expected FAIL] subtest: After a touchstart listener removes its target, touch events should be fired on the touchstart target even though an orphan and pointer events should be fired on the parent
    • PASS [expected FAIL] subtest: After a touchstart listener removes its target, touchmove event should be fired on the pointerdown target
  • CRASH [expected OK] /pointerevents/pointer_boundary_events_after_removing_last_over_element_through_innerhtml.html
  • CRASH [expected TIMEOUT] /referrer-policy/gen/top.http-rp/no-referrer-when-downgrade/svg-a-tag.http.html
  • OK [expected CRASH] /resource-timing/render-blocking-status-link.html (#41664)
    • FAIL [expected PASS] subtest: Validate render blocking status of link resources in PerformanceResourceTiming

      assert_equals: render blocking status for http://web-platform.test:8000/resource-timing/resources/empty_style.css?stylesheet-head-dynamic-docWrite should be blocking expected (string) "blocking" but got (undefined) undefined
      

  • OK /resource-timing/test_resource_timing.https.html (#25216)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)
  • CRASH [expected OK] /upgrade-insecure-requests/gen/iframe-blank-inherit.meta/unset/sharedworker-module.https.html
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • OK /webdriver/tests/classic/dismiss_alert/dismiss.py (#39098)
    • FAIL [expected PASS] subtest: test_dismiss_in_popup_window

      AssertionError: no such alert (404): No user prompt is currently active.
      

  • 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
      

  • TIMEOUT [expected OK] /webstorage/storage_session_quota_independent_from_local.window.html
  • CRASH [expected OK] /workers/WorkerLocation_search_fragment.htm
Stable unexpected results that are known to be intermittent (15)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • PASS [expected TIMEOUT] subtest: Fetching a blob URL immediately before revoking it works in <script> tags.
  • OK [expected TIMEOUT] /credential-management/credentialscontainer-frame-basics.https.html (#39430)
    • FAIL [expected TIMEOUT] subtest: navigator.credentials should be undefined in documents generated from data: URLs.

      assert_equals: expected "undefined" but got "[object CredentialsContainer]"
      

  • OK /css/css-animations/animation-iteration-event-001.html (#46004)
    • PASS [expected FAIL] subtest: Got the expected elapsedTime in the correct order
  • OK [expected ERROR] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • FAIL [expected PASS] subtest: load event does not fire on window.open('about:blank')

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • PASS [expected FAIL] subtest: Same-Document Referrer from Refresh
  • TIMEOUT [expected CRASH] /html/browsers/history/the-history-interface/001.html (#12580)
    • FAIL [expected PASS] subtest: traversing history must also traverse hash changes

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

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

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

      assert_approx_equals: The actual pitch should be close to the expected pitch. expected 880 +/- 132 but got 431.0850439882698
      

    • FAIL [expected NOTRUN] subtest: Slow-downs should change the pitch when preservesPitch=false

      assert_approx_equals: The actual pitch should be close to the expected pitch. expected 220 +/- 33 but got 431.0850439882698
      

  • OK /sanitizer-api/sanitizer-inert-document.html (#45260)
    • FAIL [expected PASS] subtest: Test whether setHTML loads the image.

      promise_test: Unhandled rejection with value: "The server observed a request. It shouldn't have."
      

    • PASS [expected FAIL] subtest: Test whether setHTMLUnsafe loads the image.
  • TIMEOUT /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.
  • 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 PASS] 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.
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission 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 form-submission 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!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.

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

Stable unexpected results (3)
  • OK /css/css-display/empty-text-baseline-001.html
    • FAIL [expected PASS] subtest: Empty second line in #inner does not generate baseline for #span

      assert_equals: expected 2 but got 0
      

    • FAIL [expected PASS] subtest: Empty second line in #inner does not generate baseline for #span with white-space: pre-line

      assert_equals: expected 2 but got 0
      

    • FAIL [expected PASS] subtest: Empty second line in #inner does not generate baseline for #span with white-space: pre

      assert_equals: expected 2 but got 0
      

  • OK /css/css-display/empty-text-baseline-002.html
    • FAIL [expected PASS] subtest: Empty content pseudo-element does not generate baseline

      assert_equals: expected 19 but got 16
      

    • FAIL [expected PASS] subtest: Empty content pseudo-element does not generate baseline with white-space: pre

      assert_equals: expected 19 but got 16
      

  • OK /css/css-fonts/generic-family-keywords-003.html
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted ui-serif (drawing text in a canvas)

      assert_equals: unquoted ui-serif does not match @font-face rule expected 40 but got 125
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted ui-sans-serif (drawing text in a canvas)

      assert_equals: unquoted ui-sans-serif does not match @font-face rule expected 40 but got 125
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted ui-monospace (drawing text in a canvas)

      assert_equals: unquoted ui-monospace does not match @font-face rule expected 40 but got 125
      

    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-rounded (drawing text in a canvas)

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

⚠️ Try run (#28721206402) failed!

@simonwuelker
simonwuelker force-pushed the stylist-font-face-rules branch from cd9d4db to 17c077b Compare July 7, 2026 16:07
simonwuelker added a commit to simonwuelker/servo that referenced this pull request Jul 7, 2026
servo#46344)

The tests rely on the same font being used in all layout queries.
However, its possible that the `Ahem` fonts loads inbetween queries,
causing timing-dependent failures. This surfaces in
servo#46271 because that PR changes the
timing of font loads.

When we wait for `document.fonts.ready` then the referenced PR reliably
passes both tests.

cc @dshin-moz

Signed-off-by: Simon Wülker <[email protected]>
@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Jul 7, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

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

Flaky unexpected result (45)
  • OK /IndexedDB/idbdatabase_deleteObjectStore.any.sharedworker.html (#45919)
    • PASS [expected FAIL] subtest: Deleted object store's name should be removed from database's list. Attempting to use a deleted IDBObjectStore should throw an InvalidStateError
  • OK /IndexedDB/idbtransaction-oncomplete.any.sharedworker.html (#45911)
    • 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
      

  • OK /_mozilla/mozilla/getBoundingClientRect.html
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • CRASH [expected OK] /_webgl/conformance/ogles/GL/mat/mat_001_to_008.html
  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • FAIL [expected PASS] subtest: WebGL test #45

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

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

      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 #49

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

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

      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
      

    • PASS [expected FAIL] subtest: WebGL test #53
    • PASS [expected FAIL] subtest: WebGL test #55
    • PASS [expected FAIL] subtest: WebGL test #57
    • PASS [expected FAIL] subtest: WebGL test #59
    • FAIL [expected PASS] subtest: WebGL test #61

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

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

      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
      

    • And 10 more unexpected results...
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-06.html
    • NOTRUN [expected PASS] subtest: Overall test
  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-14.html
  • TIMEOUT [expected OK] /_webgl/conformance2/sync/sync-webgl-specific.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
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-fonts/matching/font-unicode-PUA.html
    • PASS [expected FAIL] subtest: PUA character U+F000 is rendered with a non-generic font.
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-style: 'oblique 20deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'

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

  • 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)
  • 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/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
  • 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
  • TIMEOUT [expected OK] /fetch/content-encoding/zstd/big-window-zstd-body.tentative.https.any.sharedworker.html
    • TIMEOUT [expected FAIL] subtest: Consuming the body of a resource with too large of a zstd window size should reject

      Test timed out
      

  • TIMEOUT [expected OK] /fetch/content-encoding/zstd/big-zstd-body.https.any.html
  • 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
  • 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/navigation-unload-cross-origin.sub.window.html (#29056)
    • PASS [expected FAIL] subtest: Cross-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • FAIL [expected PASS] subtest: traversing history must also traverse hash changes

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

  • OK /html/browsers/history/the-history-interface/traverse_the_history_2.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • 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: Element with tabindex should support autofocus

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Non-HTMLElement should not support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus should support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped
    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • OK /html/semantics/embedded-content/media-elements/media_fragment_seek.html (#24114)
    • FAIL [expected PASS] subtest: Video should seek to time specified in media fragment syntax

      assert_equals: expected 4 but got 0
      

  • ERROR [expected OK] /html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html (#33778)
  • 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.
  • 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: &lt;!COM--MENT&gt;

      Test timed out
      

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

      assert_equals: Length of other host audio is correct expected 1 but got Infinity
      

  • OK /mixed-content/tentative/autoupgrades/mixed-content-cors.https.sub.html (#41123)
    • FAIL [expected PASS] subtest: Cross-Origin video should get upgraded even if CORS is set

      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'
  • 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 CRASH] /resource-timing/render-blocking-status-link.html (#41664)
    • FAIL [expected PASS] subtest: Validate render blocking status of link resources in PerformanceResourceTiming

      assert_equals: render blocking status for http://web-platform.test:8000/resource-timing/resources/empty_style.css?stylesheet-head-dynamic-docWrite should be blocking expected (string) "blocking" but got (undefined) undefined
      

  • CRASH [expected OK] /trusted-types/script-enforcement-016.html
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?11-15 (#44834)
    • PASS [expected TIMEOUT] subtest: Navigate a window via area with javascript:-urls in report-only mode.
  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in enforcing mode.
    • NOTRUN [expected FAIL] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in report-only mode.
    • NOTRUN [expected FAIL] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.
  • OK /webdriver/tests/classic/accept_alert/accept.py (#43194)
    • FAIL [expected PASS] subtest: test_accept_in_popup_window

      AssertionError: no such alert (404): No user prompt is currently active.
      

  • CRASH [expected OK] /webstorage/storage_session_setitem_quotaexceedederr.window.html
  • CRASH [expected OK] /workers/Worker-timeout-decreasing-order.html
Stable unexpected results that are known to be intermittent (18)
  • OK /IndexedDB/idbdatabase_deleteObjectStore.any.worker.html (#43776)
    • PASS [expected FAIL] subtest: Deleted object store's name should be removed from database's list. Attempting to use a deleted IDBObjectStore should throw an InvalidStateError
  • TIMEOUT [expected OK] /credential-management/credentialscontainer-frame-basics.https.html (#39430)
    • TIMEOUT [expected FAIL] subtest: navigator.credentials should be undefined in documents generated from data: URLs.

      Test timed out
      

  • 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 /dom/nodes/moveBefore/iframe-document-preserve.window.html (#43152)
    • PASS [expected FAIL] subtest: moveBefore(): cross-origin iframe is preserved: remove self
  • OK [expected TIMEOUT] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • PASS [expected TIMEOUT] subtest: [keepalive][iframe][load] mixed content redirect; setting up
  • 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
      

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

      assert_unreached: Reached unreachable code
      

  • OK [expected ERROR] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • ERROR [expected TIMEOUT] /html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html (#40387)
  • 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 [expected TIMEOUT] /html/syntax/parsing/html5lib_write.html?file=processing-instructions (#46205)
  • TIMEOUT /html/syntax/parsing/html5lib_write_single.html?file=processing-instructions (#46206)
    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?a-b-c data&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?v-123&gt;

      Test timed out
      

  • OK [expected ERROR] /intersection-observer/v2/animated-opacity.html (#40827)
  • 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/buffer-full-then-increased.html (#44408)
    • PASS [expected FAIL] subtest: Test that overflowing the buffer and immediately increasing its limit does not trigger the resourcetimingbufferfull event
  • OK /touch-events/hover-state-caused-by-compatibility-mouse-events.tentative.html (#46277)
    • FAIL [expected PASS] subtest: The compatibility mouse events should set :hover: The compatibility mouse events should be fired

      assert_equals: expected "[{ type: \"mouseover\", target: div.target },{ type: \"mousemove\", target: div.target },{ type: \"mousedown\", target: div.target },{ type: \"mouseup\", target: div.target },{ type: \"click\", target: div.target }]" but got "[]"
      

    • FAIL [expected PASS] 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

      assert_equals: expected "[{ type: \"mouseover\", target: div.target },{ type: \"mousemove\", target: div.target },{ type: \"mousedown\", target: div.target },{ type: \"mouseup\", target: div.target },{ type: \"click\", target: div.target }]" but got "[]"
      

  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • FAIL [expected PASS] subtest: Click event should be fired when touchend opens synchronous XHR

      assert_equals: expected "touchend@div, mousedown@div, mouseup@div, click@div" but got "touchend@div"
      

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

      Test timed out
      

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

✨ Try run (#28880797909) succeeded.

@mrobinson mrobinson 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.

Nice work! I have a few comments, but this already looks much better than what we have.

Comment thread components/fonts/font_context.rs Outdated
Comment thread components/layout/layout_impl.rs Outdated
Comment thread components/layout/layout_impl.rs Outdated
Comment thread components/layout/layout_impl.rs Outdated
Comment on lines +153 to +160
if let Some(window) = DomRoot::downcast::<Window>(self.global()) {
let document = window.Document();
if document.stylesheets_changed_since_last_reflow() {
window.reflow(cx, ReflowGoal::LayoutQuery(QueryMsg::BoxArea));
document.switch_font_face_set_to_loading_if_needed(cx);
}
}
}

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 don't think we want to do a synchronous reflow here every time we get the promise. Could you instead just call self.switch_to_loading() if document.stylesheets_changed_since_last_reflow()? A later layout will resolve the new promise created in that case.

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.

But that would be incorrectly return a unfulfilled promise if the stylesheets that changed did not include new web fonts right? Can web content observe that the promise is not resolved immediately?

@mrobinson mrobinson Jul 9, 2026

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.

There doesn't seem to be a way to synchronously detect if a promise has been fulfilled: https://stackoverflow.com/questions/30564053/how-can-i-synchronously-determine-a-javascript-promises-state. In any case, a small amount of unusual behavior here is probably a better cost to pay than a synchronous reflow.

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.

A bit more context: calling document.fonts.ready is a common thing to do in script and it would be both web content visible and unexpected if that did a synchronous reflow.

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.

Another problem I just thought of is that FontFaceSet is supposed to fire events when it switches to loading or finishes loading fonts. We don't implement that yet iirc, but it means that we don't want to switch to loading unless we really should.

https://drafts.csswg.org/css-font-loading/#FontFaceSet-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.

The page could detect it, but that behavior still seems better than a synchronous reflow. :/ If you can think of a better way to to avoid it that's fine though...

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.

Hmm, I'm not enthused but we can try it and see if things break I suppose.

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.

Apologies, it seems like Blink and Gecko both flush layout when getting the promise, so we should likely be doing that to. I think you can restore the original code here before landing.

Comment thread components/fonts/font_context.rs Outdated
Comment thread components/fonts/font_context.rs Outdated
Comment thread components/fonts/font_context.rs Outdated
Comment on lines +1 to +3
[font-face-007.html]
[@font-face from shadow applies to :host]
expected: FAIL

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 the reason we are failing these now is that stylesheet rules inside of shadow roots are not included in the call to iter_extra_data_origins(), so there is a real regression here as previously shadow root-level stylesheets were completely mixed with document-level ones. I think that's an acceptable regression until we properly integrate them into the cascade (either scoped to their shadow roots or not -- as only WebKit seems to do this properly).

@servo-highfive servo-highfive added S-needs-code-changes Changes have not yet been made that were requested by a reviewer. S-awaiting-review There is new code that needs to be reviewed. and removed S-awaiting-review There is new code that needs to be reviewed. S-needs-code-changes Changes have not yet been made that were requested by a reviewer. labels Jul 9, 2026
@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Jul 9, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

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

Flaky unexpected result (42)
  • ERROR [expected OK] /_mozilla/mozilla/hit-test-pos-fixed.html
  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • FAIL [expected PASS] subtest: WebGL test #45

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

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

      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 #49

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

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

      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
      

    • PASS [expected FAIL] subtest: WebGL test #53
    • PASS [expected FAIL] subtest: WebGL test #55
    • PASS [expected FAIL] subtest: WebGL test #57
    • PASS [expected FAIL] subtest: WebGL test #59
    • FAIL [expected PASS] subtest: WebGL test #61

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

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

      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
      

    • And 18 more unexpected results...
  • 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-17.html
  • CRASH [expected OK] /_webgl/conformance2/wasm/readpixels-2gb-in-4gb-wasm-memory.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
      

  • 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)
  • OK [expected TIMEOUT] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • PASS [expected TIMEOUT] subtest: [keepalive][iframe][load] mixed content redirect; setting up
  • 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
  • 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/refresh/same-document-refresh.html (#34597)
    • FAIL [expected PASS] subtest: Same-Document Referrer from Refresh

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

  • OK /html/browsers/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 [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)&amp;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"
      

  • CRASH [expected ERROR] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with empty fragments should work.

      Test timed out
      

  • 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
      

  • CRASH [expected ERROR] /html/semantics/forms/the-select-element/customizable-select/select-appearance-button-after-span.html
  • CRASH [expected TIMEOUT] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_useractivation.html
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write.html?file=comments01
    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR --&gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR --!&gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR --! &gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR --!\n&gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR -- &gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR -- &lt;QUX&gt; -- MUX --&gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR -- &lt;QUX&gt; -- MUX --!&gt;BAZ

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: FOO&lt;!-- BAR -- &lt;QUX&gt; -- MUX -- &gt;BAZ

      Test timed out
      

    • NOTRUN [expected PASS] subtest: FOO&lt;!----&gt;BAZ
    • NOTRUN [expected PASS] subtest: FOO&lt;!---&gt;BAZ
    • And 6 more unexpected results...
  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write.html?file=tests1 (#46224)
    • TIMEOUT [expected PASS] subtest: &lt;!COM--MENT&gt;

      Test timed out
      

  • TIMEOUT [expected OK] /html/syntax/parsing/html5lib_write.html?file=tests6
    • TIMEOUT [expected PASS] subtest: &lt;!doctype html&gt;&lt;/head&gt; &lt;head&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;!doctype html&gt;&lt;form&gt;&lt;div&gt;&lt;/form&gt;&lt;div&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;!doctype html&gt;&lt;title&gt;&amp;amp;&lt;/title&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;!doctype html&gt;&lt;title&gt;&lt;!--&amp;amp;--&gt;&lt;/title&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;!doctype&gt;

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;!---x

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;frameset&gt;&lt;/frameset&gt;\nfoo

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: &lt;frameset&gt;&lt;/frameset&gt;\n&lt;noframes&gt;

      Test timed out
      

    • NOTRUN [expected PASS] subtest: &lt;frameset&gt;&lt;/frameset&gt;\n&lt;div&gt;
    • NOTRUN [expected PASS] subtest: &lt;frameset&gt;&lt;/frameset&gt;\n&lt;/html&gt;
    • And 29 more unexpected results...
  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html (#45151)
    • TIMEOUT [expected FAIL] subtest: Post-navigation state reset.

      Test timed out
      

  • OK /html/webappapis/user-prompts/print-during-unload.html (#35944)
    • FAIL [expected PASS] subtest: print() during unload

      assert_array_equals: expected property 1 to be "destination" but got "error: window.print is not a function" (expected array ["start", "destination"] got ["start", "error: window.print is not a function"])
      

  • OK /infrastructure/testdriver/click_iframe.html
    • FAIL [expected PASS] subtest: TestDriver click on a document in an iframe

      Unhandled rejection: assert_unreached: click failed Reached unreachable code
      

  • OK /paint-timing/with-lcp/fcp-document-opacity-image.html (#43068)
    • FAIL [expected PASS] subtest: Test that FCP after opacity change is not a larger value than LCP

      assert_equals: First contentful paint marked too early.  expected 0 but got 1
      

  • 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 /pointerevents/compat/pointerevent_touch_target_after_pointerdown_target_removed.tentative.html (#42813)
    • FAIL [expected PASS] subtest: After a pointerdown listener removes its target, touch events should be fired on the touchstart target even though an orphan and pointer events should be fired on the parent

      assert_equals: expected "[ { type: pointerdown, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: touchstart, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchend, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; } ]" but got "[ { type: pointerdown, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: touchstart, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchend, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerdown, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; } ]"
      

    • FAIL [expected PASS] subtest: After a pointerdown listener removes its target, touchmove event should be fired on the pointerdown target

      assert_equals: expected "[ { type: pointerdown, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: touchstart, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchmove, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchend, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; } ]" but got "[ { type: pointerdown, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: touchstart, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchmove, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: touchend, target: Element node &lt;div id=\"pointerDownTarget\"&gt;&lt;/div&gt; }, { type: pointermove, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerdown, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; }, { type: pointerup, target: Element node &lt;div id=\"pointerDownTargetParent\"&gt;&lt;/div&gt; } ]"
      

  • OK /pointerevents/pointerevent_pointercapture_in_frame.html?pen (#45536)
    • FAIL [expected PASS] subtest: Test penpointer 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 penpointer 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 /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
      

  • CRASH [expected TIMEOUT] /referrer-policy/gen/top.http-rp/no-referrer-when-downgrade/svg-a-tag.http.html
  • 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
      

  • CRASH [expected OK] /trusted-types/TrustedTypePolicyFactory-createPolicy-unenforced.html
  • 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.
  • OK /upgrade-insecure-requests/gen/sharedworker-classic-data.http-rp/upgrade/fetch.https.html
    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to cross-http-downgrade origin and downgrade redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to cross-http-downgrade origin and no-redirect redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to cross-https origin and downgrade redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to same-http-downgrade origin and downgrade redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to same-http-downgrade origin and no-redirect redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for fetch to same-https origin and downgrade redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

  • OK /upgrade-insecure-requests/gen/sharedworker-classic-data.meta/upgrade/websocket.https.html
    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for websocket to cross-ws-downgrade origin and no-redirect redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

    • FAIL [expected PASS] subtest: Upgrade-Insecure-Requests: Expects allowed for websocket to same-ws-downgrade origin and no-redirect redirection from https context.

      assert_equals: The resource request should be 'allowed'. expected "allowed" but got "blocked"
      

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

      Test timed out
      

  • TIMEOUT [expected OK] /webstorage/storage_local_quota_independent_from_session.window.html
Stable unexpected results that are known to be intermittent (15)
  • TIMEOUT [expected OK] /credential-management/credentialscontainer-frame-basics.https.html (#39430)
    • TIMEOUT [expected FAIL] subtest: navigator.credentials should be undefined in documents generated from data: URLs.

      Test timed out
      

  • 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 [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-site - Not sent to non-trustworthy same-origin destination

      Test timed out
      

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

      assert_unreached: Reached unreachable code
      

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

  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-requestsubmit.html (#44098)
    • TIMEOUT [expected FAIL] subtest: Replace before load, triggered by formElement.requestSubmit()

      Test timed out
      

  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-submit.html (#44028)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/src_object_blob.html (#40340)
    • PASS [expected TIMEOUT] subtest: HTMLMediaElement.srcObject blob
  • OK [expected TIMEOUT] /html/syntax/parsing/html5lib_write.html?file=processing-instructions (#46205)
  • TIMEOUT /html/syntax/parsing/html5lib_write_single.html?file=processing-instructions (#46206)
    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?something&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?something&gt;&lt;span&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?something good&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?something else is good&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?one&gt;&lt;?two&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?a$&gt;&lt;?b$&gt;&lt;?good?&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?hey there?&gt;

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: &lt;body&gt;&lt;?hey there?&gt;

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: &lt;body&gt;&lt;?hey?there&gt;
    • NOTRUN [expected FAIL] subtest: &lt;body&gt;&lt;?hey\tthere=1?&gt;
    • And 112 more unexpected results...
  • OK /html/webappapis/dynamic-markup-insertion/document-write/iframe_005.html (#43671)
    • PASS [expected FAIL] subtest: document.write external script into iframe write back into parent
  • OK /touch-events/hover-state-caused-by-compatibility-mouse-events.tentative.html (#46277)
    • FAIL [expected PASS] subtest: The compatibility mouse events should set :hover: The compatibility mouse events should be fired

      assert_equals: expected "[{ type: \"mouseover\", target: div.target },{ type: \"mousemove\", target: div.target },{ type: \"mousedown\", target: div.target },{ type: \"mouseup\", target: div.target },{ type: \"click\", target: div.target }]" but got "[]"
      

    • FAIL [expected PASS] 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

      assert_equals: expected "[{ type: \"mouseover\", target: div.target },{ type: \"mousemove\", target: div.target },{ type: \"mousedown\", target: div.target },{ type: \"mouseup\", target: div.target },{ type: \"click\", target: div.target }]" but got "[]"
      

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

  • 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 PASS] 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.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

✨ Try run (#29014102680) succeeded.

@simonwuelker

Copy link
Copy Markdown
Member Author

this is ready for another round of review.

Comment thread components/fonts/font_context.rs
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Jul 9, 2026
@simonwuelker
simonwuelker force-pushed the stylist-font-face-rules branch from a4e2ce3 to 92f1a14 Compare July 9, 2026 15:36
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Jul 9, 2026
Signed-off-by: Simon Wülker <[email protected]>
@simonwuelker
simonwuelker force-pushed the stylist-font-face-rules branch from 92f1a14 to 62b5749 Compare July 9, 2026 15:38
@simonwuelker
simonwuelker enabled auto-merge July 9, 2026 15:44
@simonwuelker
simonwuelker added this pull request to the merge queue Jul 9, 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 Jul 9, 2026
Merged via the queue into servo:main with commit 32d6e70 Jul 9, 2026
31 checks passed
@simonwuelker
simonwuelker deleted the stylist-font-face-rules branch July 9, 2026 18:06
@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 Jul 9, 2026
pull Bot pushed a commit to Patreos998/servo that referenced this pull request Jul 10, 2026
…6436)

This is something I had written for
servo#46271 but I got confused about
if/when multiple `@font-face` rules with the same family name can apply
at the same time. We now properly remove `@font-face` rules when a rule
with higher cascade priority is inserted and we don't insert them when a
conflicting rule with higher priority already exists.

Testing: A new test starts to pass (and is no longer intermittent)
Fixes servo#35935
Fixes servo#35520

---------

Signed-off-by: Simon Wülker <[email protected]>
shubhamg13 pushed a commit to shubhamg13/servo that referenced this pull request Jul 16, 2026
This was supposed to be implemented as part of
servo#46271 but I forgot to hook up the
code that actually skips dispatching a new request when there is already
one to the same URL.

Testing: This should not change existing behaviour but *may* reduce
intermittency by virtue of making fewer network requests.

Signed-off-by: Simon Wülker <[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

3 participants