Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layout: Add support for table rows, columns, rowgroups and colgroups #31341

Merged
merged 1 commit into from Feb 20, 2024

Conversation

mrobinson
Copy link
Member

@mrobinson mrobinson commented Feb 13, 2024

This adds support for table rows, columns, rowgroups and colgroups.
There are few additions here:

  1. The creation of fragments, which allows script queries and hit
    testing to work properly. These fragments are empty as all cells are
    still direct descendants of the table fragment.
  2. Properly handling size information from tracks and track groups as
    well as frustrating rules about reordering rowgroups.
  3. Painting a background seemlessly across track groups and groups. This
    is a thing that isn't done in legacy layout (nor WebKit)!

This causes some tests to start failing, because it exposes our lack of
support for collapse in tables.

Co-authored-by: Oriol Brufau obrufau@igalia.com


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • There are tests for these changes

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Feb 14, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Feb 14, 2024
Copy link

🔨 Triggering try run (#7898358409) for Linux WPT layout-2020

Copy link

Test results for linux-wpt-layout-2020 from try job (#7898358409):

Flaky unexpected result (16)
  • CRASH [expected PASS] /_webgl/conformance/glsl/bugs/temp-expressions-should-not-crash.html (#22050)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-with-non-reserved-words.html (#16216)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/out-of-bounds-uniform-array-access.html (#26225)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT [expected FAIL] /css/css-animations/animation-delay-010.html (#26573)
  • OK /css/cssom-view/MediaQueryList-addListener-removeListener.html (#24569)
    • PASS [expected FAIL] subtest: listeners are called correct number of times
  • OK /css/cssom-view/scroll-behavior-smooth-navigation.html (#29564)
    • FAIL [expected PASS] subtest: Smooth scrolling while doing history navigation. assert_not_equals: Shouldn't be scrolled to top anymore. got disallowed value 0
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - HTTPS downgrade (header not sent) Test timed out
  • OK /fetch/private-network-access/worker-blob-fetch.tentative.window.html (#30064)
    • PASS [expected FAIL] subtest: public to public: success.
  • 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=''
    • PASS [expected FAIL] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'
  • OK /html/browsers/history/the-history-interface/traverse_the_history_2.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • FAIL [expected PASS] /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if
      allow-popups-to-escape-sandbox is used assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: 0x00 in value (normal form)
  • TIMEOUT /resource-timing/test_resource_timing.https.html (#25216)
    • FAIL [expected PASS] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img) assert_equals: expected 6403072 but got 6402816
  • OK [expected TIMEOUT] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • TIMEOUT [expected OK] /webmessaging/without-ports/018.html (#24485)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, javascript: Test timed out
Stable unexpected results that are known to be intermittent (16)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-uniform-packing-restrictions.html (#28103)
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-weight: '400' should prefer '350 399' over '351 398'
    • FAIL [expected PASS] subtest: Matching font-weight: '430' should prefer '450 460' over '500' assert_equals: Unexpected font on test element expected 487 but got 532
    • PASS [expected FAIL] subtest: Matching font-weight: '501' should prefer '500' over '450 460'
    • FAIL [expected PASS] subtest: Matching font-weight: '399' should prefer '400' over '450 460' assert_equals: Unexpected font on test element expected 487 but got 532
    • PASS [expected FAIL] subtest: Matching font-weight: '399' should prefer '500 501' over '502 510'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 20deg' should prefer 'oblique 40deg 50deg' over 'oblique 10deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 21deg' should prefer 'oblique 21deg' over 'oblique 30deg 60deg'
    • FAIL [expected PASS] subtest: Matching font-style: 'oblique 10deg' should prefer 'oblique 10deg' over 'oblique 5deg' assert_equals: Unexpected font on test element expected 487 but got 532
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 10deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'
    • FAIL [expected PASS] subtest: Matching font-style: 'oblique -21deg' should prefer 'oblique -21deg' over 'oblique -60deg -40deg' assert_equals: Unexpected font on test element expected 487 but got 532
  • TIMEOUT /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-origin destination, no attributes
  • TIMEOUT /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-referrer.window.html (#29081)
    • FAIL [expected TIMEOUT] subtest: origin referrer policy used to create the starting page assert_equals: Sanity check: opened window's referrer is set correctly expected "http://web-platform.test:8000/" but got ""
    • TIMEOUT [expected NOTRUN] subtest: no-referrer referrer policy used to create the starting page Test timed out
  • 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/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • 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 2 (expected array [6, 3] got [6, 2])
  • 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 [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if
      allow-popups-to-escape-sandbox is used assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.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"
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • 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"
  • TIMEOUT [expected OK] /html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html (#23205)
    • NOTRUN [expected PASS] subtest: Check that rel=noopener with target=_self does a normal load
  • OK [expected TIMEOUT] /html/webappapis/dynamic-markup-insertion/opening-the-input-stream/remove-initial-about-blankness.window.html (#28684)
    • FAIL [expected TIMEOUT] subtest: Double-check: without document.open(), Window reuse indeed happens assert_equals: expected (string) "Hello world!" but got (undefined) undefined
  • TIMEOUT /html/webappapis/scripting/events/compile-event-handler-settings-objects.html (#24246)
    • FAIL [expected TIMEOUT] subtest: The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document assert_equals: expected "/html/webappapis/scripting/events/resources/open-window.html" but got "blank"
  • OK [expected TIMEOUT] /webmessaging/with-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
Stable unexpected results (5)
  • PASS [expected TIMEOUT] /css/css-tables/collapsed-border-remove-cell.html
  • PASS [expected TIMEOUT] /css/css-tables/paint/row-background-paint-remove-last-cell.html
  • OK /custom-elements/reactions/customized-builtins/HTMLTableColElement.html
    • PASS [expected FAIL] subtest: span on HTMLTableColElement must enqueue an attributeChanged reaction when adding a new attribute
    • PASS [expected FAIL] subtest: span on HTMLTableColElement must enqueue an attributeChanged reaction when replacing an existing attribute
  • OK /html/dom/idlharness.https.html?include=HTML.*
    • PASS [expected FAIL] subtest: HTMLTableColElement interface: attribute span
    • PASS [expected FAIL] subtest: HTMLTableColElement interface: document.createElement("colgroup") must inherit property "span" with the proper type
    • PASS [expected FAIL] subtest: HTMLTableColElement interface: document.createElement("col") must inherit property "span" with the proper type
  • OK /html/dom/reflection-tabular.html
    • PASS [expected FAIL] subtest: colgroup.span: typeof IDL attribute
    • PASS [expected FAIL] subtest: colgroup.span: IDL get with DOM attribute unset
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to -2147483649
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to -2147483648
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to -36
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to -1
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to 1
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to ""
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to "-"
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to "+"
    • And 118 more unexpected results...

Copy link

⚠️ Try run (#7898358409) failed.

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Feb 14, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Feb 14, 2024
Copy link

🔨 Triggering try run (#7904250249) for Linux WPT layout-2020

Copy link

Test results for linux-wpt-layout-2020 from try job (#7904250249):

Flaky unexpected result (16)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-with-non-reserved-words.html (#16216)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/out-of-bounds-uniform-array-access.html (#26225)
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /css/cssom-view/MediaQueryList-addListener-removeListener.html (#24569)
    • PASS [expected FAIL] subtest: listeners are called correct number of times
  • OK /css/cssom-view/scroll-behavior-smooth-navigation.html (#29564)
    • FAIL [expected PASS] subtest: Smooth scrolling while doing history navigation. assert_not_equals: Shouldn't be scrolled back to top yet. got disallowed value 0
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - HTTPS downgrade (header not sent) Test timed out
  • TIMEOUT /fetch/metadata/generated/element-img-environment-change.https.sub.html (#30111)
    • FAIL [expected TIMEOUT] subtest: sec-fetch-site - Cross-site, no attributes promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
    • TIMEOUT [expected NOTRUN] subtest: sec-fetch-site - Same site, no attributes Test timed out
  • 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/javascript-url-return-value-handling-dynamic.html (#28066)
    • FAIL [expected PASS] subtest: 0041 set in href="" targeting a frame and clicked assert_equals: expected "A" but got ""
    • FAIL [expected PASS] subtest: 0080 00FF set in href="" targeting a frame and clicked assert_equals: expected "�ÿ" but got ""
    • FAIL [expected PASS] subtest: 0080 00FF 0100 set in href="" targeting a frame and clicked assert_equals: expected "�ÿĀ" but got ""
  • 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/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK /html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html (#29046)
    • PASS [expected FAIL] subtest: first argument: absolute url
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • OK /html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html (#23205)
    • FAIL [expected PASS] subtest: Check that rel=noopener with target=_self does a normal load this.openedWindow.findLink is not a function
  • OK [expected ERROR] /html/semantics/scripting-1/the-script-element/defer-script/async-script.html?reload (#29054)
  • OK /html/webappapis/dynamic-markup-insertion/document-write/module-tla-delayed.html (#29137)
    • FAIL [expected PASS] subtest: document.write in an imported module assert_true: onload must be called expected true got false
  • TIMEOUT [expected OK] /webmessaging/without-ports/017.html (#24486)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, about:blank Test timed out
Stable unexpected results that are known to be intermittent (14)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-uniform-packing-restrictions.html (#28103)
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-weight: '400' should prefer '351 398' over '501 550'
    • PASS [expected FAIL] subtest: Matching font-weight: '430' should prefer '420 440' over '450 460'
    • FAIL [expected PASS] subtest: Matching font-weight: '430' should prefer '450 460' over '500' assert_equals: Unexpected font on test element expected 487 but got 532
    • PASS [expected FAIL] subtest: Matching font-weight: '500' should prefer '450 460' over '400'
    • PASS [expected FAIL] subtest: Matching font-weight: '501' should prefer '500' over '450 460'
    • PASS [expected FAIL] subtest: Matching font-weight: '399' should prefer '340 360' over '200 300'
    • PASS [expected FAIL] subtest: Matching font-weight: '399' should prefer '200 300' over '400'
    • FAIL [expected PASS] subtest: Matching font-weight: '399' should prefer '400' over '450 460' assert_equals: Unexpected font on test element expected 487 but got 532
    • PASS [expected FAIL] subtest: Matching font-style: 'normal' should prefer 'oblique 10deg 40deg' over 'oblique 20deg 30deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique 0deg 10deg' over 'oblique 40deg 50deg'
    • And 1 more unexpected results...
  • 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
  • TIMEOUT /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-referrer.window.html (#29081)
    • FAIL [expected TIMEOUT] subtest: origin referrer policy used to create the starting page assert_equals: Sanity check: opened window's referrer is set correctly expected "http://web-platform.test:8000/" but got ""
    • TIMEOUT [expected NOTRUN] subtest: no-referrer referrer policy used to create the starting page Test timed out
  • 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_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 2 (expected array [6, 3] got [6, 2])
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if
      allow-popups-to-escape-sandbox is used assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.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/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
    • 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 [expected TIMEOUT] /html/webappapis/dynamic-markup-insertion/opening-the-input-stream/remove-initial-about-blankness.window.html (#28684)
    • FAIL [expected TIMEOUT] subtest: Double-check: without document.open(), Window reuse indeed happens assert_equals: expected (string) "Hello world!" but got (undefined) undefined
  • TIMEOUT /html/webappapis/scripting/events/compile-event-handler-settings-objects.html (#24246)
    • FAIL [expected TIMEOUT] subtest: The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document assert_equals: expected "/html/webappapis/scripting/events/resources/open-window.html" but got "blank"
  • ERROR /resource-timing/content-type-parsing.html (#29131)
    • TIMEOUT [expected FAIL] subtest: mime-type 16 : text/html;charset=�gbk Test timed out
    • NOTRUN [expected TIMEOUT] subtest: mime-type 17 : text/html;charset= gbk
  • TIMEOUT /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)

Copy link

✨ Try run (#7904250249) succeeded.

Copy link
Contributor

@Loirooriol Loirooriol left a comment

Choose a reason for hiding this comment

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

Some complaints from clippy

.translate(containing_block.origin.to_vector());
self.maybe_push_hit_test_for_style_and_tag(
builder,
&style,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
&style,
style,

Comment on lines 631 to 634
fn build_background_image<'b>(
&mut self,
builder: &mut DisplayListBuilder,
source: background::Source<'a>,
painter: BackgroundPainter<'b>,
Copy link
Contributor

Choose a reason for hiding this comment

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

-    fn build_background_image<'b>(
+    fn build_background_image(
         &mut self,
         builder: &mut DisplayListBuilder,
-        painter: BackgroundPainter<'b>,
+        painter: BackgroundPainter<'_>,

Comment on lines 577 to 579
fn build_background_for_painter<'b>(
&mut self,
painter: BackgroundPainter<'b>,
builder: &mut DisplayListBuilder,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
fn build_background_for_painter<'b>(
&mut self,
painter: BackgroundPainter<'b>,
builder: &mut DisplayListBuilder,
fn build_background_for_painter(
&mut self,
painter: BackgroundPainter<_>,
builder: &mut DisplayListBuilder,

rect: LogicalRect<Length>,
style: ServoArc<ComputedValues>,
) -> Self {
let writing_mode = style.writing_mode.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let writing_mode = style.writing_mode.clone();
let writing_mode = style.writing_mode;

Comment on lines 171 to 172
outer_min_content_width += pbm.padding_border_sums.inline.into();
outer_max_content_width += pbm.padding_border_sums.inline.into();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
outer_min_content_width += pbm.padding_border_sums.inline.into();
outer_max_content_width += pbm.padding_border_sums.inline.into();
outer_min_content_width += pbm.padding_border_sums.inline;
outer_max_content_width += pbm.padding_border_sums.inline;

if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline {
let baseline = Au::from(cell_rect.start_corner.block) + row_baseline;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let baseline = Au::from(cell_rect.start_corner.block) + row_baseline;
let baseline = cell_rect.start_corner.block + row_baseline;

@mrobinson
Copy link
Member Author

Thanks @Loirooriol, I think I've fixed those clippy warnings, but there are so many in Layout 2020 it's a bit hard to tell. It would be nice to clean them all up.

Copy link
Contributor

@Loirooriol Loirooriol left a comment

Choose a reason for hiding this comment

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

I think I didn't have time to review all the files, I will go through it again, but for now I guess I can submit the comments that I had.

Comment on lines 157 to 160
let display = &fragment.style.get_box().display;
if display.inside() == style::values::specified::box_::DisplayInside::Flow &&
display.outside() ==
style::values::specified::box_::DisplayOutside::Inline
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be

Suggested change
let display = &fragment.style.get_box().display;
if display.inside() == style::values::specified::box_::DisplayInside::Flow &&
display.outside() ==
style::values::specified::box_::DisplayOutside::Inline
use style::properties::longhands::display::computed_value::T as Display;
if fragment.style.get_box().display == Display::Inline {

Comment on lines +232 to +237
for row_group in self.table.row_groups.iter() {
if row_group.track_range.start > n {
return row_group.track_range.start - 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this use a binary search?

}

if let Some(remove_from) = remove_from {
self.table.column_groups.truncate(remove_from - 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this use remove_from?

}
}

fn regenerate_track_ranges(&mut self) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be called twice, it could be better to remove the calls from move_row_group_to_front/end, make them return a bool if something changes, and call regenerate_track_ranges from reorder_first_thead_and_tfoot depending on these bools.

Comment on lines 360 to 365
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.splice(0..0, removed_row_group);
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems simpler to do this without splice():

Suggested change
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.splice(0..0, removed_row_group);
let removed_row_group = self.table.row_groups.remove(index_to_move);
self.table.row_groups.insert(0, removed_row_group);

Comment on lines 402 to 407
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.extend(removed_row_group);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto

Suggested change
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.extend(removed_row_group);
let removed_row_group = self.table.row_groups.remove(index_to_move);
self.table.row_groups.push(removed_row_group);

Comment on lines 352 to 365
let removed_rows: Vec<TableTrack> = self
.table
.rows
.splice(row_range, std::iter::empty())
.collect();
self.table.rows.splice(0..0, removed_rows);

// Move the group itself.
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.splice(0..0, removed_row_group);
Copy link
Contributor

Choose a reason for hiding this comment

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

In fact the entire thing may be simpler without splice() at all?

Suggested change
let removed_rows: Vec<TableTrack> = self
.table
.rows
.splice(row_range, std::iter::empty())
.collect();
self.table.rows.splice(0..0, removed_rows);
// Move the group itself.
let removed_row_group: Vec<TableTrackGroup> = self
.table
.row_groups
.splice(index_to_move..index_to_move + 1, std::iter::empty())
.collect();
self.table.row_groups.splice(0..0, removed_row_group);
let mut removed_rows = self.table.rows.split_off(row_range.end + 1);
self.table.rows.rotate_right(row_range.len());
self.table.rows.append(&mut removed_rows);

Comment on lines 315 to 339
let mut current_row_group = None;
for (row_index, row) in self.table.rows.iter().enumerate() {
if current_row_group == row.group_index {
continue;
}

if let Some(new_group_index) = row.group_index {
if let Some(new_group) = self.table.row_groups.get_mut(new_group_index) {
new_group.track_range = row_index..self.table.rows.len();
}
}

if let Some(current_group_index) = current_row_group {
if let Some(current_group) = self.table.row_groups.get_mut(current_group_index) {
current_group.track_range.end = row_index;
}
}

current_row_group = row.group_index;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems clearer to me like this:

Suggested change
let mut current_row_group = None;
for (row_index, row) in self.table.rows.iter().enumerate() {
if current_row_group == row.group_index {
continue;
}
if let Some(new_group_index) = row.group_index {
if let Some(new_group) = self.table.row_groups.get_mut(new_group_index) {
new_group.track_range = row_index..self.table.rows.len();
}
}
if let Some(current_group_index) = current_row_group {
if let Some(current_group) = self.table.row_groups.get_mut(current_group_index) {
current_group.track_range.end = row_index;
}
}
current_row_group = row.group_index;
}
let mut current_row_group_index = None;
for (row_index, row) in self.table.rows.iter().enumerate() {
if current_row_group_index == row.group_index {
continue;
}
if let Some(current_group_index) = current_row_group_index {
self.table.row_groups[current_group_index].track_range.end = row_index;
}
current_row_group_index = row.group_index;
if let Some(current_group_index) = current_row_group_index {
self.table.row_groups[current_group_index].track_range.start = row_index;
}
}
if let Some(current_group_index) = current_row_group_index {
self.table.row_groups[current_group_index].track_range.end = self.table.rows.len();
}

if let AttrValue::UInt(ref mut s, ref mut val) = attr {
if *val == 0 {
*val = 1;
*s = "1".into();
Copy link
Contributor

Choose a reason for hiding this comment

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

If value isn't even a number, AttrValue::UInt will preserve the string even though the number will default to DEFAULT_SPAN.

So for consistency I think the string shouldn't be changed to "1" here?

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
Copy link

🔨 Triggering try run (#7961737364) for Linux WPT

Copy link

Test results for linux-wpt-layout-2020 from try job (#7961737364):

Flaky unexpected result (13)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-with-non-reserved-words.html (#16216)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/out-of-bounds-uniform-array-access.html (#26225)
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-weight: '500' should prefer '400' over '350 399'
    • PASS [expected FAIL] subtest: Matching font-stretch: '90%' should prefer '50% 80%' over '60% 70%'
    • PASS [expected FAIL] subtest: Matching font-stretch: '90%' should prefer '110% 140%' over '120% 130%'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 20deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique -50deg -40deg' over 'italic'
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - HTTPS downgrade (header not sent) Test timed out
  • TIMEOUT /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • FAIL [expected TIMEOUT] subtest: sec-fetch-site - Not sent to non-trustworthy same-site destination, no attributes promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
    • TIMEOUT [expected NOTRUN] subtest: sec-fetch-site - Not sent to non-trustworthy cross-site destination, no attributes Test timed out
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html (#29048)
    • PASS [expected FAIL] subtest: Navigating to a different document with link click
  • 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 [expected OK] /html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html (#29046)
    • TIMEOUT [expected FAIL] subtest: first argument: absolute url Test timed out
  • FAIL [expected PASS] /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if
      allow-popups-to-escape-sandbox is used assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
  • ERROR /resource-timing/content-type-parsing.html (#29131)
    • FAIL [expected TIMEOUT] subtest: mime-type 16 : text/html;charset=�gbk assert_equals: expected (string) "text/html" but got (undefined) undefined
    • TIMEOUT [expected NOTRUN] subtest: mime-type 17 : text/html;charset= gbk Test timed out
  • 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] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
Stable unexpected results that are known to be intermittent (10)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-uniform-packing-restrictions.html (#28103)
    • NOTRUN [expected PASS] subtest: Overall test
  • OK /css/cssom-view/scroll-behavior-smooth-navigation.html (#29564)
    • FAIL [expected PASS] subtest: Smooth scrolling while doing history navigation. assert_not_equals: Shouldn't be scrolled back to top yet. got disallowed value 0
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • FAIL [expected PASS] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='' assert_unreached: load should not be fired Reached unreachable code
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • FAIL [expected PASS] subtest: load event does not fire on window.open('about:blank') assert_unreached: load should not be fired Reached unreachable code
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • PASS [expected FAIL] subtest: Cross-origin navigation started from unload handler must be ignored
  • TIMEOUT [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected TIMEOUT] subtest: Host element with delegatesFocus including no focusable descendants should be skipped promise_test: Unhandled rejection with value: object "TypeError: host.attachShadow is not a function"
    • FAIL [expected NOTRUN] subtest: Area element should support autofocus promise_test: Unhandled rejection with value: object "TypeError: w.document.querySelector(...) is null"
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if
      allow-popups-to-escape-sandbox is used assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
  • 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"
  • TIMEOUT /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)
Stable unexpected results (2)
  • OK /css/cssom-view/client-props-inline-list-item.html
    • FAIL [expected PASS] subtest: client* returns the same for non-replaced inlines regardless of list-item-ness assert_equals: clientWidth should match expected 44 but got 0
  • OK /html/dom/reflection-tabular.html
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to 0
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to "-0"
    • PASS [expected FAIL] subtest: colgroup.span: setAttribute() to "0"
    • PASS [expected FAIL] subtest: col.span: setAttribute() to 0
    • PASS [expected FAIL] subtest: col.span: setAttribute() to "-0"
    • PASS [expected FAIL] subtest: col.span: setAttribute() to "0"

Copy link

⚠️ Try run (#7961737364) failed.

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
Copy link

🔨 Triggering try run (#7962736101) for Linux WPT

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Feb 19, 2024
Copy link

🔨 Triggering try run (#7962757948) for Linux WPT

Copy link

Test results for linux-wpt-layout-2020 from try job (#7962757948):

Flaky unexpected result (12)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • TIMEOUT [expected FAIL] subtest: Opening a blob URL in a new window immediately before revoking it works. Test timed out
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-with-non-reserved-words.html (#16216)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT [expected OK] /_webgl/conformance/uniforms/out-of-bounds-uniform-array-access.html (#26225)
    • NOTRUN [expected PASS] subtest: Overall test
  • FAIL [expected PASS] /css/css-text/line-breaking/segment-break-transformation-unremovable-3.html (#28758)
  • PASS [expected TIMEOUT] /css/css-transitions/render-blocking/no-transition-from-ua-to-blocking-stylesheet.html (#29187)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling-dynamic.html (#28066)
    • FAIL [expected PASS] subtest: 0041 set in href="" targeting a frame and clicked assert_equals: expected "A" but got ""
    • FAIL [expected PASS] subtest: 0080 00FF set in href="" targeting a frame and clicked assert_equals: expected "�ÿ" but got ""
    • FAIL [expected PASS] subtest: 0080 00FF 0100 set in href="" targeting a frame and clicked assert_equals: expected "�ÿĀ" but got ""
    • FAIL [expected PASS] subtest: D83D DE0D set in href="" targeting a frame and clicked assert_equals: expected "😍" but got ""
    • FAIL [expected PASS] subtest: DE0D 0041 set in href="" targeting a frame and clicked assert_equals: expected "\ufffdA" but got ""
  • 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/read-media/pageload-image-in-popup.html (#23849)
    • PASS [expected FAIL] subtest: The document for a standalone media file should have one child in the body.
  • OK /html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html (#29046)
    • PASS [expected FAIL] subtest: first argument: absolute url
  • TIMEOUT [expected OK] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • TIMEOUT [expected PASS] subtest: reparent-form-during-planned-navigation-task Test timed out
  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • PASS [expected FAIL] subtest: text/plain: 0x00 in name (normal form)
  • OK /html/webappapis/dynamic-markup-insertion/document-write/module-delayed.html (#27659)
    • FAIL [expected PASS] subtest: async document.write in a module assert_true: onload must be called expected true got false
Stable unexpected results that are known to be intermittent (14)
  • TIMEOUT [expected OK] /_webgl/conformance/glsl/misc/shader-uniform-packing-restrictions.html (#28103)
    • NOTRUN [expected PASS] subtest: Overall test
  • TIMEOUT /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-origin destination, no attributes
  • 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/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • FAIL [expected PASS] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='' assert_unreached: load should not be fired Reached unreachable code
  • 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
  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-referrer.window.html (#29081)
    • TIMEOUT [expected PASS] subtest: no-referrer referrer policy used to create the starting page Test timed out
  • 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 [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.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 /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 [expected ERROR] /html/semantics/scripting-1/the-script-element/defer-script/async-script.html?reload (#29054)
  • TIMEOUT /html/webappapis/scripting/events/compile-event-handler-settings-objects.html (#24246)
    • PASS [expected FAIL] subtest: The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document
  • TIMEOUT /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)
  • TIMEOUT [expected OK] /webmessaging/without-ports/017.html (#24486)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, about:blank Test timed out

Copy link

✨ Try run (#7962757948) succeeded.

Copy link
Contributor

@Loirooriol Loirooriol left a comment

Choose a reason for hiding this comment

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

The legacy expectations for the html/dom tests need to be updated.

@mrobinson mrobinson added this pull request to the merge queue Feb 20, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Feb 20, 2024
This adds support for table rows, columns, rowgroups and colgroups.
There are few additions here:

1. The createion of fragments, which allows script queries and hit
   testing to work properly. These fragments are empty as all cells are
   still direct descendants of the table fragment.
2. Properly handling size information from tracks and track groups as
   well as frustrating rules about reordering rowgroups.
3. Painting a background seemlessly across track groups and groups. This
   is a thing that isn't done in legacy layout (nor WebKit)!

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
@mrobinson mrobinson added this pull request to the merge queue Feb 20, 2024
Merged via the queue into servo:main with commit 02ae1f4 Feb 20, 2024
9 checks passed
@mrobinson mrobinson deleted the table-column-and-colgroup branch February 20, 2024 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

None yet

2 participants