Skip to content

Conversation

@jdm
Copy link
Member

@jdm jdm commented Oct 31, 2025

Rebase of #37021 with review comments applied. These changes bundle up the required information from the relevant global when a stylesheet is added so that any requests for web fonts match the specification.

Testing: Newly passing tests.
Fixes: #36590

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Oct 31, 2025
@jdm jdm added the T-linux-wpt Do a try run of the WPT label Oct 31, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Oct 31, 2025
@github-actions
Copy link

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

Copy link
Contributor

@TimvdLippe TimvdLippe left a comment

Choose a reason for hiding this comment

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

Nice! I would expect some CSP tests to start passing as well.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Oct 31, 2025
@github-actions
Copy link

⚠️ Try run (#18964463483) failed.

Copy link
Member

@mrobinson mrobinson left a comment

Choose a reason for hiding this comment

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

Looks good from the perspective of someone who worked on the font loader. I'm not sure about the origin request parameter.

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Oct 31, 2025
@jdm jdm added the T-linux-wpt Do a try run of the WPT label Oct 31, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Oct 31, 2025
@github-actions
Copy link

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

@github-actions
Copy link

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

Flaky unexpected result (26)
  • OK /IndexedDB/idbfactory_open.any.html
    • FAIL [expected PASS] subtest: Calling open() with version argument 1.5 should not throw.

      assert_equals: version expected 1 but got 9007199254740991
      

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

      Test timed out
      

  • TIMEOUT [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • 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
  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • PASS [expected FAIL] subtest: WebGL test #45
    • PASS [expected FAIL] subtest: WebGL test #47
    • PASS [expected FAIL] subtest: WebGL test #49
    • PASS [expected FAIL] subtest: WebGL test #51
    • FAIL [expected PASS] subtest: WebGL test #53

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

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

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

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

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

      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 #61
    • PASS [expected FAIL] subtest: WebGL test #63
    • And 6 more unexpected results...
  • 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 "41.45px"
      

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

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

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

      assert_equals: quoted serif matches  @font-face rule expected 125 but got 40
      

    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-sans-serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-rounded (drawing text in a canvas)
  • 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 /html/browsers/browsing-the-web/navigating-across-documents/009.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url with document.write and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /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
  • 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_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 1 (expected array [6, 3] got [6, 1])
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected PASS] /html/browsers/origin/origin-keyed-agent-clusters/popups-crash.https.html
  • FAIL [expected PASS] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • PASS [expected FAIL] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-reload-location-reload.html (#32595)
    • FAIL [expected PASS] subtest: Reloading iframe loading='lazy' before it is loaded: location.reload

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

  • OK /preload/preload-xhr.html (#39092)
    • FAIL [expected PASS] subtest: Make an XHR request immediately after creating link rel=preload.

      assert_equals: resources/dummy.xml?token=7ef7bd6e-d82c-4cdc-b654-9c725a045412 expected 1 but got 0
      

  • ERROR /service-workers/idlharness.https.any.html (#36250)
    • PASS [expected TIMEOUT] subtest: ServiceWorkerContainer interface: operation register((TrustedScriptURL or USVString), optional RegistrationOptions)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation enable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation disable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation setHeaderValue(ByteString)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation getState()
  • OK /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • PASS [expected FAIL] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.
    • PASS [expected FAIL] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
  • OK /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected FAIL] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.
  • OK [expected TIMEOUT] /webmessaging/with-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe
  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
Stable unexpected results that are known to be intermittent (16)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.worker.html (#39277)
    • FAIL [expected PASS] subtest: IDBCursor continuePrimaryKey() on object store cursor

      assert_throws_dom: continuePrimaryKey() should throw if source is not an index function "function() {
              cursor.continuePrimaryKey(2, 2);
            }" threw object "TypeError: cursor.continuePrimaryKey is not a function" that is not a DOMException InvalidAccessError: property "code" is equal to undefined, expected 15
      

  • OK /IndexedDB/idbobjectstore_getAll.any.html (#39276)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • OK /IndexedDB/idbobjectstore_getAll.any.worker.html (#39400)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • OK /IndexedDB/key-conversion-exceptions.any.html (#39305)
    • FAIL [expected PASS] subtest: IDBCursor continue() method with throwing/invalid keys

      assert_throws_exactly: key conversion with throwing getter should rethrow function "() => {
            receiver[method](key);
          }" threw object "TypeError: receiver[method] is not a function" but we expected it to throw object "getter: throwing from getter"
      

  • OK /IndexedDB/key-conversion-exceptions.any.worker.html (#39284)
    • FAIL [expected PASS] subtest: IDBCursor continue() method with throwing/invalid keys

      assert_throws_exactly: key conversion with throwing getter should rethrow function "() => {
            receiver[method](key);
          }" threw object "TypeError: receiver[method] is not a function" but we expected it to throw object "getter: throwing from getter"
      

    • FAIL [expected PASS] subtest: IDBCursor update() method with throwing/invalid keys

      assert_throws_exactly: throwing getter should rethrow during clone function "() => {
            cursor.update(value);
          }" threw object "TypeError: cursor.update is not a function" but we expected it to throw object "getter: throwing from getter"
      

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

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

  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-mode
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination
  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected NOTRUN] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

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

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

      Test timed out
      

  • OK /html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm (#37173)
    • FAIL [expected PASS] subtest: default object size after src is removed

      assert_equals: expected "300px" but got "320px"
      

  • OK /html/semantics/forms/historical.html (#28568)
    • PASS [expected FAIL] subtest: <input name=isindex> should not be supported
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: CORS (fetch): main
  • OK /trusted-types/trusted-types-navigation.html?01-05 (#38975)
    • PASS [expected FAIL] subtest: Navigate a window via anchor with javascript:-urls in enforcing mode.
    • PASS [expected FAIL] subtest: Navigate a window via anchor with javascript:-urls in report-only mode.
    • FAIL [expected PASS] subtest: Navigate a frame via anchor with javascript:-urls in enforcing mode.

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

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

@github-actions
Copy link

✨ Try run (#18981318512) succeeded.

@TimvdLippe
Copy link
Contributor

@jdm
Copy link
Member Author

jdm commented Nov 2, 2025

Aha, the culprit is:

FetchResponseMsg::ProcessCspViolations(..) => DownloaderResponseResult::InProcess,
. We drop the CSP notification on the ground.

@servo-highfive servo-highfive added the S-needs-rebase There are merge conflict errors. label Nov 2, 2025
@servo-highfive servo-highfive removed the S-needs-rebase There are merge conflict errors. label Nov 2, 2025
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Nov 2, 2025
@TimvdLippe TimvdLippe added this pull request to the merge queue Nov 2, 2025
@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 Nov 2, 2025
@jdm jdm removed this pull request from the merge queue due to a manual request Nov 2, 2025
@github-actions
Copy link

github-actions bot commented Nov 2, 2025

⚠️ Try run (#19017822404) failed.

@jdm
Copy link
Member Author

jdm commented Nov 2, 2025

If my try push in https://github.com/servo/servo/actions/runs/19019558687 goes well, I would like to split this work up into three PRs in sequence:

  1. this PR without the CSP changes
  2. make webfonts critical subresources that block load events and remove our Ahem.css user stylesheet injection (f363bc2)
  3. the CSP webfont changes from this PR

That will hopefully put us in a position where reporting CSP violations for web fonts doesn't break tests that expect a particular CSP failure but see a violation from our injected Ahem.ttf instead.

@TimvdLippe
Copy link
Contributor

Sounds like a good plan to me

@mrobinson
Copy link
Member

Another alternative here would be to ensure that every platform has Ahem loaded into its system font cache before running the tests. It seems like this could be done by injecting it manually on Servo startup.

@mrobinson
Copy link
Member

2. make webfonts critical subresources that block load events and remove our Ahem.css user stylesheet injection (f363bc2)

About this, I wonder why it is necessary? We are currently waiting for all web fonts to load before taking screenshots. Is there another case that I'm missing here?

@jdm
Copy link
Member Author

jdm commented Nov 18, 2025

  1. make webfonts critical subresources that block load events and remove our Ahem.css user stylesheet injection (f363bc2)

About this, I wonder why it is necessary? We are currently waiting for all web fonts to load before taking screenshots. Is there another case that I'm missing here?

There's a window of time between finishing fetching an external style sheet and starting fetching any web fonts that it defines. Without our injected user style sheet present, we end up sometimes taking a screenshot during that window so the expected font is not applied.

uthmaniv and others added 5 commits November 23, 2025 01:55
Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Nov 23, 2025
@jdm jdm enabled auto-merge November 23, 2025 07:33
@jdm jdm disabled auto-merge November 23, 2025 07:35
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
@jdm jdm enabled auto-merge November 23, 2025 07:39
@jdm jdm added this pull request to the merge queue Nov 23, 2025
@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 Nov 23, 2025
}));
}

fn clone(&self) -> Box<dyn CspViolationHandler> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we derive Clone for this struct? It looks like the default implementation to me

Copy link
Member Author

@jdm jdm Nov 23, 2025

Choose a reason for hiding this comment

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

We can derive Clone, I don't think it really helps us at all since we still need to write this method.

pub csp_handler: Box<dyn CspViolationHandler>,
}

impl Clone for WebFontDocumentContext {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, can't we derive Clone?

Copy link
Member Author

@jdm jdm Nov 23, 2025

Choose a reason for hiding this comment

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

Nope—the presence of the trait object makes that impossible, and trying to use trait CspViolationHandler: Clone means it can't be used as a trait object.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Nov 23, 2025
Merged via the queue into servo:main with commit bbbfe6d Nov 23, 2025
32 checks passed
@jdm jdm deleted the issue_36590 branch November 23, 2025 08:49
@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 Nov 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web font requests are missing many settings

5 participants