Skip to content

layout: Use a consistent definition of "document white space"#44424

Merged
mrobinson merged 1 commit into
servo:mainfrom
mrobinson:align-definition-of-document-white-space
Apr 28, 2026
Merged

layout: Use a consistent definition of "document white space"#44424
mrobinson merged 1 commit into
servo:mainfrom
mrobinson:align-definition-of-document-white-space

Conversation

@mrobinson

Copy link
Copy Markdown
Member

Because the definition of "document white space" differed in various
places in Servo layout, it was possible for the flexbox container
builder to expect to be able to build an inline formatting context from
text that was ultimately determined to be empty by the inline formatting
context builder. This led to a BoxSlot not being properly filled (a
thing that should never happen) and an assertion failing.

This change fixes that issue.

Testing: This change adds a new WPT crash test.
Fixes: #43550.

@servo-wpt-sync

Copy link
Copy Markdown
Collaborator

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

self.text
.bytes()
.all(|byte| matches!(byte, b' ' | b'\n' | b'\t'))
.all(|byte| InlineFormattingContextBuilder::is_document_white_space(byte.into()))

@Loirooriol Loirooriol Apr 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have tested Firefox and Chrome, and U+000C doesn't create a flex item:

<!DOCTYPE html>
<div style="display: flex; justify-content: space-between">&#x000c;<span>item</span></div>

But it's not included in is_document_white_space

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 wasn't sure how to test this, so it is good to have confirmation. I've updated the change to include the form feed character (U+00C), which also happens to be WhatWG's definition of ASCII white space and the Rust is_ascii_whitespace function.

@mrobinson mrobinson force-pushed the align-definition-of-document-white-space branch from 84880d4 to 2458b1f Compare April 22, 2026 15:52
@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Apr 22, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Apr 22, 2026
@github-actions

Copy link
Copy Markdown

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

@servo-wpt-sync

Copy link
Copy Markdown
Collaborator

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

@github-actions

Copy link
Copy Markdown

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

Flaky unexpected result (31)
  • 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
  • OK /IndexedDB/transaction-create_in_versionchange.any.html (#44200)
    • FAIL [expected PASS] subtest: Attempt to create new transactions inside a versionchange transaction

      assert_array_equals: events expected property 4 to be "open_rq.success: [object IDBDatabase]" but got "complete_count.success: 2" (expected array ["versionchange_add.success: 1", "versionchange_count.success: 0", "versionchange_add2.success: 2", "versionchange_txn.complete", "open_rq.success: [object IDBDatabase]", "complete_count.success: 2", "complete2_get.success: 1"] got ["versionchange_add.success: 1", "versionchange_count.success: 0", "versionchange_add2.success: 2", "versionchange_txn.complete", "complete_count.success: 2", "open_rq.success: [object IDBDatabase]", "complete2_get.success: 1"])
      

  • CRASH [expected OK] /_webgl/conformance2/extensions/oes-shader-multisample-interpolation.html
  • 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
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-041.html
  • FAIL [expected PASS] /css/css-backgrounds/border-image-repeat-space-9.html
  • OK /css/css-fonts/generic-family-keywords-002.html (#40929)
    • FAIL [expected PASS] subtest: font-family: -webkit-serif treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-sans-serif treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-cursive treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-fantasy treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-monospace treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-system-ui treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-math treated as &lt;font-family&gt;, not &lt;generic-name&gt;

      assert_equals: expected 30 but got 50
      

    • PASS [expected FAIL] subtest: font-family: -webkit-generic(fangsong) treated as &lt;font-family&gt;, not &lt;generic-name&gt;
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(kai) treated as &lt;font-family&gt;, not &lt;generic-name&gt;
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(khmer-mul) treated as &lt;font-family&gt;, not &lt;generic-name&gt;
    • And 12 more unexpected results...
  • FAIL [expected PASS] /css/filter-effects/kernel-unit-length-002.html
  • CRASH [expected OK] /fetch/api/cors/cors-preflight-not-cors-safelisted.any.html
  • OK /fetch/metadata/window-open.https.sub.html (#40339)
    • FAIL [expected PASS] subtest: Same-site window, forced, reloaded

      The operation is insecure.
      

  • 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/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • PASS [expected FAIL] subtest: load event does not fire on window.open('about:blank')
  • CRASH [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/redirect-to-unparseable-url.html
  • 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.html (#44028)
  • 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_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])
      

  • OK /html/browsers/windows/browsing-context-names/duplicate-name-order.html (#34623)
    • PASS [expected FAIL] subtest: Duplicate name lookup order
  • ERROR [expected OK] /html/canvas/offscreen/text/2d.text.measure.getActualBoundingBox.tentative.html (#43710)
  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • FAIL [expected PASS] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due

      uncaught exception: Error: assert_unreached: The iframe from which the meta came from must not refresh Reached unreachable code
      

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

      Test timed out
      

  • TIMEOUT [expected OK] /pointerevents/compat/pointerevent_touch-action_two-finger_interaction.html
    • 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 [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)
    • TIMEOUT [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
  • OK /webdriver/tests/classic/element_click/events.py
    • FAIL [expected PASS] subtest: test_event_mousemove

      AssertionError: assert 3 == 4
      

  • 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
      

  • CRASH [expected OK] /workers/WorkerGlobalScope_importScripts.htm
Stable unexpected results that are known to be intermittent (18)
  • OK /IndexedDB/idbdatabase_deleteObjectStore.any.html (#43823)
    • 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] /_mozilla/mozilla/window-resize-event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • ERROR /_webgl/conformance2/textures/misc/tex-3d-size-limit.html (#44383)
    • FAIL [expected PASS] subtest: WebGL test #77

      assert_true: successfullyParsed should be true (of type boolean). Was undefined (of type undefined). expected true got false
      

  • OK [expected CRASH] /content-security-policy/meta/sandbox-iframe.html (#43478)
  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted system-ui (drawing text in a canvas)

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

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

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

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

      assert_equals: quoted generic(fangsong) matches  @font-face rule expected 125 but got 40
      

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

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

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

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

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

      Test timed out
      

  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/sandboxed-iframe.https.window.html (#41704)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Cross-site

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

  • TIMEOUT /fetch/metadata/generated/css-images.https.sub.tentative.html (#42229)
    • FAIL [expected PASS] subtest: content sec-fetch-site - Same-Origin -&gt; Same Origin

      assert_unreached: Reached unreachable code
      

  • 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
      

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

      Test timed out
      

  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html (#39703)
    • FAIL [expected PASS] subtest: Meta refresh of the original iframe is not blocked if moved into a sandboxed iframe

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

  • OK /mixed-content/tentative/autoupgrades/mixed-content-cors.https.sub.html (#41123)
    • PASS [expected FAIL] subtest: Cross-Origin video should get upgraded even if CORS is set
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
  • CRASH [expected OK] /resource-timing/render-blocking-status-link.html (#41664)
  • OK /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)
  • OK /trusted-types/trusted-types-reporting.html (#43737)
    • PASS [expected FAIL] subtest: Trusted Type violation report: creating a forbidden-but-not-reported policy.
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute

@github-actions

Copy link
Copy Markdown

✨ Try run (#24788358751) succeeded.

@mrobinson mrobinson force-pushed the align-definition-of-document-white-space branch from 2458b1f to ab97e93 Compare April 28, 2026 07:28
@servo-wpt-sync

Copy link
Copy Markdown
Collaborator

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

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Apr 28, 2026
@mrobinson mrobinson enabled auto-merge April 28, 2026 08:00
@mrobinson

Copy link
Copy Markdown
Member Author

Hrm. The DCO bot seems to be wedged.

@mukilan

mukilan commented Apr 28, 2026

Copy link
Copy Markdown
Member

Hrm. The DCO bot seems to be wedged.

Perhaps you can try doing a rebase + force push again.

Because the definition of "document white space" differed in various
places in Servo layout, it was possible for the flexbox container
builder to expect to be able to build an inline formatting context from
text that was ultimately determined to be empty by the inline formatting
context builder. This led to a `BoxSlot` not being properly filled (a
thing that should never happen) and an assertion failing.

This change fixes that issue.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
@mrobinson mrobinson force-pushed the align-definition-of-document-white-space branch from ab97e93 to 2c780ba Compare April 28, 2026 08:49
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Apr 28, 2026
@servo-wpt-sync

Copy link
Copy Markdown
Collaborator

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

@mrobinson mrobinson added this pull request to the merge queue Apr 28, 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 Apr 28, 2026
Merged via the queue into servo:main with commit 22114bd Apr 28, 2026
33 checks passed
@mrobinson mrobinson deleted the align-definition-of-document-white-space branch April 28, 2026 10:16
@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 Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion fails with ja.wikipedia.org

6 participants