8000 layout: Add incremental box tree construction for inline boxes by coding-joedow · Pull Request #38084 · servo/servo · GitHub
[go: up one dir, main page]

Skip to content

Conversation

coding-joedow
Copy link
Contributor

This changes extend the incremental box tree construction for inline boxes. Since an InlineItem can be split into multiple InlineItems by a block element, the reason such an inline item is marked as damaged may simply be the removal of the block element or the need to reconstruct its box tree. Therefore, under the current LayoutDamage design, theoretically, even damaged inline items might still have some of their splits reusable. However, based on the principle of simplicity and effectiveness, this PR only considers reusing undamaged inline boxes.

Testing: This should not change observable behavior and is thus covered by existing WPT tests.

@Loirooriol Loirooriol added the T-linux-wpt Do a try run of the WPT label Jul 15, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 15, 2025
Copy link

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

Copy link

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

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

      Test timed out
      

  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • 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
    • PASS [expected FAIL] subtest: WebGL test #65
    • PASS [expected FAIL] subtest: WebGL test #67
  • CRASH [expected ERROR] /_webgl/conformance2/textures/misc/tex-input-validation.html
  • OK /fetch/content-length/api-and-duplicate-headers.any.worker.html (#35197)
    • FAIL [expected PASS] subtest: fetch() and duplicate Content-Length/Content-Type headers

      promise_test: Unhandled rejection with value: object "TypeError: Network error occurred"
      

  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-user
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • PASS [expected FAIL] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'
  • 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
      

  • FAIL [expected PASS] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with non-existent fragments should work.

      Test
      8000
       timed out
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • TIMEOUT [expected FAIL] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      Test timed out
      

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.html (#33948)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Dynamic import failed"
      

  • TIMEOUT /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)
  • TIMEOUT [expected CRASH] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
Stable unexpected results that are known to be intermittent (18)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • FAIL [expected PASS] /css/css-transitions/render-blocking/no-transition-from-ua-to-blocking-stylesheet.html (#29187)
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • ERROR [expected TIMEOUT] /fetch/fetch-later/quota/same-origin-iframe/max-payload.tentative.https.window.html (#35210)
  • 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-origin destination
  • 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)
    • FAIL [expected PASS] subtest: Same-origin navigation started from unload handler must be ignored

      assert_equals: expected "?pass" but got "?fail"
      

  • 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
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /html/semantics/forms/historical.html (#28568)
    • FAIL [expected PASS] subtest: <input name=isindex> should not be supported

      assert_regexp_match: expected object "/\?isindex=x$/" but got "about:blank"
      

  • 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 /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: CORS (style): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.css?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=style should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: success (script): main
    • PASS [expected FAIL] subtest: 404 (script): main
    • FAIL [expected PASS] subtest: CORS (script): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.js?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: success (xhr): main
    • PASS [expected FAIL] subtest: CORS (xhr): main
    • FAIL [expected PASS] subtest: MIME-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?pipe=header%28Content-Type%2Ctext%2Fnotjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

  • TIMEOUT [expected OK] /resource-timing/nested-context-navigations-iframe.html (#24311)
    • TIMEOUT [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent, even after history navigations by the parent

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Test that iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe refreshes are not observable by the parent
  • 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()
Stable unexpected results (1)
  • OK /custom-elements/form-associated/form-disabled-callback.html
    • PASS [expected FAIL] subtest: A disabled form-associated custom element should not submit an entry for it

Copy link

⚠️ Try run (#16294456385) failed.

@jschwe jschwe added the T-linux-wpt Do a try run of the WPT label Jul 21, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 21, 2025
Copy link

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

InlineItem::StartInlineBox(inline_box) => Some(inline_box.clone()),
_ => None,
})
.collect();
Copy link
Member

Choose a reason for hiding this comment

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

.iter().rev().filter_map(...).collect() builds a new vector even if there are no matches

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's true. But it should be unlikely.

Copy link

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

Flaky unexpected result (20)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(nastaliq)
  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#31559)
  • FAIL [expected PASS] /css/css-tables/paint/table-border-paint-caption-change.html (#38036)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination

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

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

      Test timed out
      

  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • PASS [expected FAIL] subtest: traversing history must also traverse hash changes
  • 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_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • 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_popups_nonescaping-2.html (#22154)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: Basic test (normal form)
  • OK /html/semantics/scripting-1/the-script-element/execution-timing/077.html (#22139)
    • FAIL [expected PASS] subtest: adding several types of scripts through the DOM and removing some of them confuses scheduler

      assert_array_equals: expected property 1 to be "Script #1 ran" but got "Script #3 ran" (expected array ["Script #2 ran", "Script #1 ran", "Script #3 ran", "Script #4 ran"] got ["Script #2 ran", "Script #3 ran", "Script #4 ran", "Script #1 ran"])
      

  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • CRASH [expected OK] /resource-timing/tentative/document-initiated.html (#37785)
  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • ERROR [expected OK] /workers/constructors/Worker/Worker-constructor.html (#22991)
Stable unexpected results that are known to be intermittent (17)
  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • 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
      

  • FAIL [expected PASS] /css/css-transitions/render-blocking/no-transition-from-ua-to-blocking-stylesheet.html (#29187)
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.tentative.https.window.html (#35176)
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • PASS [expected FAIL] subtest: sec-fetch-site - Same origin, no options - registration
  • 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/empty-iframe-load-event.html (#29066)
    • FAIL [expected PASS] subtest: Check execution order from nested timeout

      assert_equals: Expected nested setTimeout to run second expected true but got false
      

    • FAIL [expected PASS] subtest: Check execution order on load handler

      assert_equals: Expected onload to run first expected false but got true
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • FAIL [expected PASS] subtest: Same-origin navigation started from unload handler must be ignored

      assert_equals: expected "?pass" but got "?fail"
      

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

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

    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      promise_test: Unhandled rejection with value: object "TypeError: w.document.querySelector(...) is null"
      

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /html/semantics/forms/historical.html (#28568)
    • FAIL [expected PASS] subtest: <input name=isindex> should not be supported

      assert_regexp_match: expected object "/\?isindex=x$/" but got "about:blank"
      

  • OK /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • PASS [expected FAIL] subtest: success (xhr): main
    • PASS [expected FAIL] subtest: 404 (xhr): main
    • PASS [expected FAIL] subtest: CORS (xhr): main
    • FAIL [expected PASS] subtest: Decode-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=header%28Content-Type%2Ctext%2Fjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

    • FAIL [expected PASS] subtest: MIME-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?pipe=header%28Content-Type%2Ctext%2Fnotjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

  • TIMEOUT [expected OK] /webmessaging/with-ports/018.html (#24485)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, javascript:

      Test timed out
      

Copy link

✨ Try run (#16413162149) succeeded.

block_in_inline_splits: Vec<Vec<ArcRefCell<InlineItem>>>,

/// If the [`InlineBox`] of an inline-level element is not damaged, it can be reused
/// to support incremental layout. Since an [`InlineBox`] can be split by block
Copy link
Contributor

Choose a reason for hiding this comment

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

"Since" introduces a subordinated clause, but here there wouldn't be an independent clause owning it.

Suggested change
/// to support incremental layout. Since an [`InlineBox`] can be split by block
/// to support incremental layout. An [`InlineBox`] can be split by block

if let Some(LayoutBox::InlineLevel(inline_level_box)) = old_layout_box {
let old_block_in_inline_splits: Vec<ArcRefCell<InlineBox>> = inline_level_box
.iter()
.rev() // reverse to facilate the `Vec::pop` operation
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this better than using a VecDeque?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it is unnecessary to introduce the new data structure. No push operation is needed for old_block_in_inline_splits.

Comment on lines 285 to 295
self.push_control_character_string(inline_box.borrow().base.style.bidi_control_chars().0);

// Don't push a `SharedInlineStyles` if we are pushing this box when splitting
// an IFC for a block-in-inline split. Shared styles are pushed as part of setting
// up the second split of the IFC.
if inline_box.is_first_split {
if inline_box.borrow().is_first_split {
self.shared_inline_styles_stack
.push(inline_box.shared_inline_styles.clone());
.push(inline_box.borrow().shared_inline_styles.clone());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Better just borrow once?

Suggested change
self.push_control_character_string(inline_box.borrow().base.style.bidi_control_chars().0);
// Don't push a `SharedInlineStyles` if we are pushing this box when splitting
// an IFC for a block-in-inline split. Shared styles are pushed as part of setting
// up the second split of the IFC.
if inline_box.is_first_split {
if inline_box.borrow().is_first_split {
self.shared_inline_styles_stack
.push(inline_box.shared_inline_styles.clone());
.push(inline_box.borrow().shared_inline_styles.clone());
}
let borrowed_inline_box = inline_box.borrow();
self.push_control_character_string(borrowed_inline_box.base.style.bidi_control_chars().0);
// Don't push a `SharedInlineStyles` if we are pushing this box when splitting
// an IFC for a block-in-inline split. Shared styles are pushed as part of setting
// up the second split of the IFC.
if borrowed_inline_box.is_first_split {
self.shared_inline_styles_stack
.push(borrowed_inline_box.shared_inline_styles.clone());
}
std::mem::drop(borrowed_inline_box);

izip!(self.inline_box_stack.iter(), block_in_inline_splits)
{
let old_block_in_inline_splits = std::mem::take(&mut self.old_block_in_inline_splits);
for (identifier, historical_inline_boxes, old_inline_boxes) in izip!(
Copy link
Contributor

Choose a reason for hiding this comment

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

I think "historical" and "old" aren't clearly telling these apart.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
@coding-joedow coding-joedow force-pushed the incremental-inline-boxes-construction branch from 4bdbdfc to 8e000e4 Compare July 22, 2025 01:51
@Loirooriol Loirooriol added this pull request to the merge queue Jul 25, 2025
Merged via the queue into servo:main with commit 5cd57f9 Jul 25, 2025
21 checks passed
@coding-joedow coding-joedow deleted the incremental-inline-boxes-construction branch July 25, 2025 14:51
minghuaw pushed a commit to minghuaw/servo that referenced this pull request Aug 1, 2025
…#38084)

This changes extend the incremental box tree construction for inline
boxes. Since an `InlineItem` can be split into multiple `InlineItem`s by
a block element, the reason such an inline item is marked as damaged may
simply be the removal of the block element or the need to reconstruct
its box tree. Therefore, under the current LayoutDamage design,
theoretically, even damaged inline items might still have some of their
splits reusable. However, based on the principle of simplicity and
effectiveness, this PR only considers reusing undamaged inline boxes.

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
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.

4 participants
0