Skip to content

script: Prescan byte stream to determine encoding before parsing document#41376

Merged
simonwuelker merged 9 commits intoservo:mainfrom
simonwuelker:sniff-encodings
Dec 19, 2025
Merged

script: Prescan byte stream to determine encoding before parsing document#41376
simonwuelker merged 9 commits intoservo:mainfrom
simonwuelker:sniff-encodings

Conversation

@simonwuelker
Copy link
Copy Markdown
Contributor

@simonwuelker simonwuelker commented Dec 18, 2025

Servo currently completely ignores <meta charset> tags. When we find one with an encoding that is incompatible to the current one, then we should reload the page and start over with the new encoding. A common optimization that has even made its way into the specification is to wait for a few bytes to arrive and inspect them for meta tags, so the browser is able to use the correct encoding from the very beginng.

In practice, I've run into problems with our WPT harness when reloading the page after meta tags. Therefore, this change implement the optimization first, so we never have to reload when running WPT. I've implemented prescanning in a way where we wait for 1024 bytes to arrive or for one second to pass, whichever one happens first.

This causes a large number of web platform tests to flip around. I've looked at most of the new failures and I believe they're reasonable.

Testing: New tests start to pass.
Part of #6414

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Dec 18, 2025
Comment on lines +1 to 2
[in-script.html]
expected: FAIL
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These charset/in-* tests fail because the prescanning algorithm doesn't know that it should ignore things like <script><meta charset="windows-1251"></script>. I'll fix this in a followup, since this PR is large enough already.

Copy link
Copy Markdown
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.

Amazing work @simonwuelker!

Comment on lines +164 to +177
if let Some(encoding) = encoding_detector.buffer(chunk) {
document.set_encoding(encoding);
let buffered_bytes = mem::take(&mut encoding_detector.buffered_bytes);
*self = Self::Decoding(NetworkDecoder {
decoder: Some(LossyDecoder::new_encoding_rs(
encoding,
NetworkSink::default(),
)),
encoding,
});
return self.push(&buffered_bytes, document);
}

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

Suggested change
if let Some(encoding) = encoding_detector.buffer(chunk) {
document.set_encoding(encoding);
let buffered_bytes = mem::take(&mut encoding_detector.buffered_bytes);
*self = Self::Decoding(NetworkDecoder {
decoder: Some(LossyDecoder::new_encoding_rs(
encoding,
NetworkSink::default(),
)),
encoding,
});
return self.push(&buffered_bytes, document);
}
None
encoding_detector.buffer(chunk).map(|encoding| {
document.set_encoding(encoding);
let buffered_bytes = mem::take(&mut encoding_detector.buffered_bytes);
*self = Self::Decoding(NetworkDecoder {
decoder: Some(LossyDecoder::new_encoding_rs(
encoding,
NetworkSink::default(),
)),
encoding,
});
return self.push(&buffered_bytes, document);
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Assigning to *self in the closure doesn't seem to be accepted by the borrow checker, because it also needs encoding_detector.buffered_bytes, which is borrowed from self.

Comment on lines +2 to +4
expected: ERROR
[WebGL test #3]
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.

Interesting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Likely a unrelated intermittent issue that I missed in my try run (:

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

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (24)
  • OK /_mozilla/webxr/create_session.https.html
    • FAIL [expected PASS] subtest: create_session

      can't access property "simulateDeviceConnection", navigator.xr.test is undefined
      

  • OK /_mozilla/webxr/obtain_frame.https.html
    • FAIL [expected PASS] subtest: obtain_frame

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "simulateDeviceConnection", navigator.xr.test is undefined"
      

  • ERROR [expected TIMEOUT] /_mozilla/webxr/sessionavailable.https.html
  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 1
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 2
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • FAIL [expected PASS] subtest: sec-fetch-site - Same origin, no options - registration

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • CRASH [expected OK] /html/anonymous-iframe/local-storage.tentative.https.window.html
  • OK /html/browsers/browsing-the-web/navigating-across-documents/008.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

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

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

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

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with "top" fragments should work.

      Test timed out
      

  • OK /html/semantics/embedded-content/media-elements/media_fragment_seek.html (#24114)
    • PASS [expected FAIL] subtest: Video should seek to time specified in media fragment syntax
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-assign.html (#32863)
    • FAIL [expected PASS] subtest: Navigating iframe loading='lazy' before it is loaded: location.assign

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

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

      Test timed out
      

  • OK /html/semantics/forms/form-submission-0/jsurl-form-submit.tentative.html (#36489)
    • PASS [expected FAIL] subtest: Verifies that form submissions scheduled inside javascript: urls take precedence over the javascript: url's return value.
  • CRASH [expected OK] /import-maps/csp/unsafe-inline.html
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: CORS (fetch): main
  • CRASH [expected ERROR] /trusted-types/SharedWorker-setTimeout-setInterval.html
  • CRASH [expected OK] /trusted-types/eval-function-constructor.html
  • CRASH [expected OK] /trusted-types/trusted-types-reporting-for-DedicatedWorker-ServiceWorkerContainer-register.https.html
  • CRASH [expected ERROR] /wasm/webapi/status.any.serviceworker.html
  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe
  • OK /xhr/send-redirect.htm (#32026)
    • FAIL [expected PASS] subtest: XMLHttpRequest: send() - Redirects (basics) (308, GET, content.py)

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

Stable unexpected results that are known to be intermittent (31)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.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/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/idbrequest-onupgradeneeded.any.html (#38895)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • OK /IndexedDB/idbrequest-onupgradeneeded.any.worker.html (#38971)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • 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 "() =&gt; {
            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 "() =&gt; {
            cursor.update(value);
          }" threw object "TypeError: cursor.update 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 "() =&gt; {
            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 "() =&gt; {
            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)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • CRASH [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • PASS [expected FAIL] subtest: Delete layer invalidates @font-face
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(kai)
  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-monospace (drawing text in a canvas)
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Null value should submit nothing
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-site - Same site
    • PASS [expected FAIL] subtest: sec-fetch-mode
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • PASS [expected FAIL] subtest: sec-fetch-user
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Cross-site

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • CRASH [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • PASS [expected FAIL] subtest: load event does not fire on window.open('about:blank')
  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected PASS] subtest: Non-HTMLElement should not support autofocus

      Test timed out
      

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

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

  • OK /html/semantics/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
  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html (#41193)
    • TIMEOUT [expected PASS] subtest: Default "autoplay" feature policy ["self"] allows same-origin iframes.

      Test timed out
      

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

      Test timed out
      

  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: 0x00 in value (normal form)
  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • FAIL [expected PASS] subtest: text/plain: Basic test (formdata event)

      assert_equals: expected "basic=test\r\n" but got ""
      

    • FAIL [expected PASS] subtest: text/plain: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt\r\n" but got ""
      

  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic test (formdata event)

      assert_equals: expected "basic=test" but got ""
      

    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in value (formdata event)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: single quote in filename (formdata event)
  • 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 /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart &gt; Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
  • 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.
  • 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!\""
      

@github-actions
Copy link
Copy Markdown

✨ Try run (#20350147469) succeeded.

@simonwuelker simonwuelker added this pull request to the merge queue Dec 18, 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 Dec 18, 2025
github-merge-queue bot pushed a commit that referenced this pull request Dec 18, 2025
…ment (#41376)

Servo currently completely ignores `<meta charset>` tags. When we find
one with an encoding that is incompatible to the current one, then we
should reload the page and start over with the new encoding. A common
optimization that has even made its way into the specification is to
wait for a few bytes to arrive and inspect them for `meta` tags, so the
browser is able to use the correct encoding from the very beginng.

In practice, I've run into problems with our WPT harness when reloading
the page after `meta` tags. Therefore, this change implement the
optimization first, so we never have to reload when running WPT. I've
implemented prescanning in a way where we wait for 1024 bytes to arrive
or for one second to pass, whichever one happens first.

This causes a large number of web platform tests to flip around. I've
looked at most of the new failures and I believe they're reasonable.

Testing: New tests start to pass.
Part of #6414

---------

Signed-off-by: Simon Wülker <[email protected]>
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Dec 18, 2025
@servo-highfive servo-highfive added S-tests-failed The changes caused existing tests to fail. and removed S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. labels Dec 18, 2025
@servo-highfive servo-highfive removed the S-tests-failed The changes caused existing tests to fail. label Dec 19, 2025
@simonwuelker
Copy link
Copy Markdown
Contributor Author

Found a source of intermittency (22403fc) and fixing it gives us another 300 passes :)

@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Dec 19, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Dec 19, 2025
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (22)
  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • OK /_mozilla/webxr/create_session.https.html
    • FAIL [expected PASS] subtest: create_session

      can't access property "simulateDeviceConnection", navigator.xr.test is undefined
      

  • TIMEOUT /content-security-policy/inheritance/location-reload.html (#38983)
    • FAIL [expected PASS] subtest: location.reload() of empty iframe.

      assert_equals: Image should be blocked by CSP after reload. expected "img blocked" but got "img loaded"
      

  • FAIL [expected PASS] /css/css-backgrounds/border-image-repeat-space-9.html
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 1
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 2
  • 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 generic(nastaliq) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-sans-serif (drawing text in a canvas)
  • ERROR [expected OK] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • 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/history/the-history-interface/traverse_the_history_4.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

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

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

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

      Test timed out
      

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

  • 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=c96cf5a0-1bac-4b79-93f5-3fa3cb673eef expected 1 but got 0
      

  • CRASH [expected OK] /trusted-types/Element-setAttribute-setAttributeNS-sinks.tentative.html
  • CRASH [expected OK] /trusted-types/set-attributes-no-require-trusted-types.html
  • CRASH [expected OK] /trusted-types/trusted-types-reporting-for-Window-eval.html
  • 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)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe
  • CRASH [expected OK] /workers/Worker_ErrorEvent_bubbles_cancelable.htm
  • CRASH [expected OK] /workers/baseurl/alpha/xhr-in-moduleworker.html
Stable unexpected results that are known to be intermittent (33)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.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/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/idbrequest-onupgradeneeded.any.html (#38895)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • OK /IndexedDB/idbrequest-onupgradeneeded.any.worker.html (#38971)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • 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 "() =&gt; {
            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 "() =&gt; {
            cursor.update(value);
          }" threw object "TypeError: cursor.update 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 "() =&gt; {
            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 "() =&gt; {
            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)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /content-security-policy/frame-ancestors/frame-ancestors-path-ignored.window.html (#36468)
    • FAIL [expected PASS] subtest: A 'frame-ancestors' CSP directive with a URL that includes a path should be ignored.

      assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
      

  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(kai)
  • OK [expected TIMEOUT] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • PASS [expected TIMEOUT] subtest: [keepalive][iframe][load] mixed content redirect; setting up
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Cross-site

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • FAIL [expected PASS] subtest: sec-fetch-site - Same origin, no options - registration

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • PASS [expected FAIL] subtest: load event does not fire on window.open('about:blank')
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

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

  • TIMEOUT /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
  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-default-feature-policy.https.sub.html (#41193)
    • TIMEOUT [expected PASS] subtest: Default "autoplay" feature policy ["self"] allows same-origin iframes.

      Test timed out
      

  • OK /html/semantics/embedded-content/media-elements/media_fragment_seek.html (#24114)
    • PASS [expected FAIL] subtest: Video should seek to time specified in media fragment syntax
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: 0x00 in value (normal form)
  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • FAIL [expected PASS] subtest: text/plain: Basic test (formdata event)

      assert_equals: expected "basic=test\r\n" but got ""
      

    • FAIL [expected PASS] subtest: text/plain: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt\r\n" but got ""
      

    • PASS [expected FAIL] subtest: text/plain: Basic File test (formdata event)
    • PASS [expected FAIL] subtest: text/plain: 0x00 in name (normal form)
    • PASS [expected FAIL] subtest: text/plain: \r\n in name (formdata event)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt" but got ""
      

    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in value (normal form)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in filename (formdata event)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: single quote in name (formdata event)
  • TIMEOUT [expected ERROR] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html (#40347)
  • CRASH [expected TIMEOUT] /html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html (#21642)
  • TIMEOUT [expected CRASH] /html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.html (#21444)
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: CORS (fetch): main
  • 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 [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)
    • 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?26-30 (#38807)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.

      Test timed out
      

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

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.
Stable unexpected results (17)
  • OK /_mozilla/mozilla/document_characterSet_long.html
    • PASS [expected FAIL] subtest: document_characterSet_long
  • OK /_mozilla/mozilla/document_characterSet_short.html
    • PASS [expected FAIL] subtest: document_characterSet_short
  • OK /dom/nodes/Document-characterSet-normalization-1.html
    • PASS [expected FAIL] subtest: Name "IBM866" has label "866" (characterSet)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "866" (inputEncoding)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "866" (charset)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "cp866" (characterSet)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "cp866" (inputEncoding)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "cp866" (charset)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "csibm866" (characterSet)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "csibm866" (inputEncoding)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "csibm866" (charset)
    • PASS [expected FAIL] subtest: Name "IBM866" has label "ibm866" (characterSet)
    • And 287 more unexpected results...
  • OK /html/browsers/browsing-the-web/scroll-to-fragid/scroll-frag-non-utf8-encoded-document.html
    • PASS [expected FAIL] subtest: Fragment Navigation: fragment id should not be found in non UTF8 document
  • OK /html/syntax/charset/meta-charset-double-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta charset
  • OK /html/syntax/charset/meta-charset-no-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta charset
  • OK /html/syntax/charset/meta-charset-single-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta charset
  • OK /html/syntax/charset/meta-http-equiv-attribute-order.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta http-equiv
  • OK /html/syntax/charset/meta-http-equiv-double-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta http-equiv
  • OK /html/syntax/charset/meta-http-equiv-no-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta http-equiv
  • OK /html/syntax/charset/meta-http-equiv-single-quotes.html
    • PASS [expected FAIL] subtest: document.characterSet must be determined by meta http-equiv
  • OK /html/syntax/charset/with-inheritance.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/after-bogus.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/baseline.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-object.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-svg.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-template.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/non-ascii-in-comment-before.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/non-ascii-in-title-before.html
  • OK /html/syntax/charset/without-inheritance.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/after-bogus.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/baseline.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-object.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-svg.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/in-template.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/non-ascii-in-comment-before.html
    • PASS [expected FAIL] subtest: Check http://web-platform.test:8000/html/syntax/charset/non-ascii-in-title-before.html
  • OK /html/syntax/parsing/meta-inhead-insertion-mode.html
    • PASS [expected FAIL] subtest: Encoding specified in the 'charset' attribute should have precedence over 'content' attribute.
  • OK /html/syntax/parsing/quotes-in-meta.html
    • PASS [expected FAIL] subtest: quotes-in-meta
  • OK /html/syntax/xmldecl/xmldecl-1.html
    • PASS [expected FAIL] subtest: Check encoding windows-1251, baseline.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, cp1251.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, letter-between-xml-and-encoding.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, lt-between-xml-and-encoding.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, meta-inside-xml-charset-before-encoding.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, meta-inside-xml-encoding-before-charset.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, no-version.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, no-version-or-space.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, no-version-or-space-or-trailing-question.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1251, no-version-or-space-or-trailing-question-trailing-body.htm
    • And 8 more unexpected results...
  • OK /html/syntax/xmldecl/xmldecl-2.html
    • PASS [expected FAIL] subtest: Check encoding windows-1253, xml-and-meta.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1253, incomplete-utf-16le-and-meta.htm
    • PASS [expected FAIL] subtest: Check encoding windows-1253, incomplete-utf-16be-and-meta.htm
    • PASS [expected FAIL] subtest: Check encoding UTF-16LE, utf-16le-and-meta.htm
    • PASS [expected FAIL] subtest: Check encoding UTF-16BE, utf-16be-and-meta.htm
    • PASS [expected FAIL] subtest: Check encoding replacement, replacement.htm

@github-actions
Copy link
Copy Markdown

⚠️ Try run (#20364703193) failed.

Signed-off-by: Simon Wülker <[email protected]>
@simonwuelker simonwuelker added this pull request to the merge queue Dec 19, 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 Dec 19, 2025
Merged via the queue into servo:main with commit 8c344f5 Dec 19, 2025
29 checks passed
@simonwuelker simonwuelker deleted the sniff-encodings branch December 19, 2025 11:21
@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 Dec 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants