Commit Graph

122 Commits

Author SHA1 Message Date
Oriol Brufau
60c5977291 layout: Correctly repair OutsideMarker::list_item_style (#42825)
`OutsideMarker::repair_style()` was setting `list_item_style` to the
style of the marker, not the style of the list item.

This patch sets it to `node.parent_style(context)` instead, and it fixes
`ServoThreadSafeLayoutNode::parent_style()` to take the pseudo-element
chain into account. This requires modifying a bunch of logic to pass the
`SharedStyleContext` around.

Testing: Adding a new test

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-02-25 13:25:45 +00:00
Martin Robinson
042d95220a layout: Replace dirty root approach with flexible box tree layout (#42700)
Replace the old dirty root box tree layout approach with one that works
based on independent formatting contexts. Instead of just allowing a
single dirty root to be the source of box tree reconstruction, allow box
tree reconstruction to happen anywhere in the tree that can isolate box
tree damage from ancestors. This essentially combines damage propagation
and box tree construction into a single step.

There is currently one downside to this approach compared to the dirty
root approach which is that we currently cannot detect and start box
tree layout when the dirty has a compatible `display` and `position`
value. This can mean the scope of box tree layout extends further up the
tree. We will address this in a followup -- but have not noticed any
major performance implications (currently fragment tree layout is much
more expensive than box tree layout).

Benefits:
 1. Damage propagation now only happens under the dirty root.
 2. Future changes can limit the scope of damage up the tree and perhaps
    preserve the inline content size cache between box tree rebuilds.

Testing: This should not change behavior in a testable way (we currently
do
not have robust performance tests), so WPT test results should not
change.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Luke Warlow <lwarlow@igalia.com>
2026-02-19 14:31:13 +00:00
Oriol Brufau
2a3f23c78d Upgrade Stylo to 2026-02-02 (#42361)
This continues #41916

Changelog:
- Upstream:
360787fff5...7cd2a178d3
- Servo fixups:
e4d50e905e...d9831d464b

Stylo tracking issue: https://github.com/servo/stylo/issues/305

In particular, this adds support for `alignment-baseline` and
`baseline-shift`, and turns `vertical-align` into a shorthand of them.
This also introduces `vertical-align: center`.

Testing: Various tests improve. Some internal tests are updated because
they were wrong. And some fail because we don't support presentation
attributes on SVG elements.

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-02-09 11:16:42 +00:00
Luke Warlow
bd779d141a script: Add support for :open pseudo-class (#42195)
Add support for `:open` pseudo-class. This is supported on dialog,
details and select elements.


Stylo PR: servo/stylo#297
Testing: WPTs but also
`data:text/html,<select><option>123</option></select><style>:open {
background-color: red; }</style>`. There are some tests that now error,
these previously failed due to missing `:open` and now make it further
along hitting test_driver.send_keys() which causes them to error
Fixes: #41277.

---------

Signed-off-by: Luke Warlow <lwarlow@igalia.com>
2026-01-29 17:08:51 +00:00
Andreu Botella
b0399561d6 layout: Support content: <image> on non-pseudo-elements (#41480)
Per CSS-CONTENT-3, one of the possible values of the `content` CSS
property is `<content-replacement>`, which evaluates to a single
`<image>`. This value is also allowed on regular elements, not just on
pseudo-elements, and it will make the element into a replaced element
representing the given image, discarding its contents.

This patch implements this in `traverse_element`: if the `display` value
is not `none` or `contents`, we first check whether the `contents`
property should make the element replaced, and if it shouldn't, then we
check whether the element itself is replaced or a widget.

Per the spec, an invalid image must be treated as representing a
transparent black image with zero natural width and height – in
particular, it must not show a broken image icon. We added the method
`ReplacedContents::zero_sized_invalid_image` to implement this.

This patch adds support for image URL references, but not for color
gradients, which are treated as invalid images. The reason for this is
that currently Servo does not support gradients in
`ReplacedContentKind`. This is left as a follow-up change.

Testing: Some of the existing `css/css-content/element-replacement*` WPT
tests now pass with this patch. We also added some new ones dealing with
replacing the document root.

Fixes: #41479

Signed-off-by: Andreu Botella <andreu@andreubotella.com>
2026-01-28 17:46:18 +00:00
Luke Warlow
aad7424150 Update details to support ::details-content pseudo element. (#42107)
Update details to support `::details-content` pseudo element.

This is currently not element-backed but will support the basic styling.

This replaces the existing `::-servo-details-content` styling.

Testing: WPTs and manually using
https://demo.lukewarlow.dev/css-forms.html

<img width="159" height="66" alt="image"
src="https://github.com/user-attachments/assets/8e72e7f3-2b49-43c6-9a4e-dbea0586739e"
/>

Stylo PR: https://github.com/servo/stylo/pull/292

Signed-off-by: Luke Warlow <lwarlow@igalia.com>
2026-01-28 14:52:50 +00:00
Martin Robinson
4a9c95ac8e layout: Handle selection during display list construction (#41963)
Instead of handling selection in text input during box tree / fragment
tree construction, fully handle it during display list construction.
This means that when the selection changes in script, it updates
automatically in the `FragmentTree` and only a new display list is
necessary. This avoids a layout while changing the selection in text
fields.

Testing: This fixes a few rendering issues, but these are very hard
to isolate and test for. It causes one test to start failing, but this
is
because a cursor that wasn't rendered properly now starts showing
up.
Fixes: #41920.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2026-01-21 08:04:15 +00:00
Martin Robinson
90f568f962 fonts: Store ByteIndex as a usize (#42012)
This value is supposed to represent a UTF-8 code point offset or
length. It should never be negative and we often need to convert it to a
`usize`, so we can store it as a `usize`.

Testing: This should not change behavior so existing tests should
suffice.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2026-01-19 18:30:04 +00:00
Rod Borovyk
eacdbd9a34 layout: Accept lengths in arbitrary units for SVG width and height (#40761)
Previously it was only possible to set width and height of SVG elements
in pixels. These changes allow parsing other units like em using a CSS
parser in SVGSVGElement and resolving them to computed values in the
layout code.

Testing: Tested manually
Fixes: -

---------

Signed-off-by: Rodion Borovyk <rodion.borovyk@gmail.com>
2026-01-19 13:31:27 +00:00
Oriol Brufau
a5752da7d6 Upgrade Stylo to 2026-01-01 (#41916)
This continues #41696

Changelog:
- Upstream:
ab77635ba3...360787fff5
- Servo fixups:
0c47f9cb52...71737ad5c8

Stylo tracking issue: https://github.com/servo/stylo/issues/286

Testing: Various tests are now passing

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-01-15 10:58:48 +00:00
Martin Robinson
30fa32714e Remove Servo's custom Range implementation (#41880)
Servo `Range` type probably predates the `Range` type in the standard
library. The fact that there are two `Range` types in Servo is often
very confusing. The internal type is only used for byte indices in glyph
runs. This change removes the internal generic `Range` in favor of a
small wrapper around a native Rust `Range`.

It's likely that there are more improvements that could be done here,
such as reusing `Utf8CodePointIndex`, but this code is going to change a
lot soon and these ranges might soon be replaced with actual glyph
ranges. We are going to be looking to remove `TextByteRange` entirely.
This is just an intermediate step.

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

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2026-01-13 15:31:47 +00:00
Martin Robinson
cbb23c72af script: Implement all user agent widgets for form controls with shadow DOM (#41760)
This change makes it so that all form controls are implemented with
shadow DOM, completely removing the legacy text content and selection
code paths for form controls. The motivation for this change is:

- to allow properly hit testing against the text nodes of `<textarea>`
  and other widgets. This is important for implementing mouse-based
  selection on the page.
- to simplify the way that form controls are implemented in general and
  to prepare the way for proper implementations of the user interface of
  other controls.

Testing: This should not change observable behavior at the moment,so
should be covered by existing WPT tests.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2026-01-09 01:11:20 +00:00
aquaThirsty
d808cc15d0 change #[allow]s to #[expect]s (#41635)
Changed most #[allow]s to #[expect]s, mainly for
clippy::too_many_arguments

Removed unfulfilled expectations

This is my first opensource contribution, so please let me know if
anything should
be done differently.

Testing: Refactor
Part of: #40838

---------

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
Signed-off-by: TimurBora <timurborisov5561@gmail.com>
Co-authored-by: Tim van der Lippe <TimvdLippe@users.noreply.github.com>
2026-01-03 10:54:27 +00:00
Oriol Brufau
3ee05f7c7d script: Restrict box tree damage from changes in original display (#41475)
When the original display of an absolutely positioned element changes,
the static position can be affected. However, the static position is
only used when both insets in the same axis are `auto`.

Therefore, this patch avoids dirtying the box tree when both axes have a
non-auto inset.

Testing: Not needed, this should have no observable behavior change

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-12-22 12:58:45 +00:00
batu_hoang
1aab8186b7 selectors::Element::parent() shouldn't cross shadow tree boundary (#40977)
ServoLayoutElement::parent_element() method shouldn't cross shadow tree
boundary.
`inheritance_parent` uses `traversal_parent`

Testing: 
`tests/wpt/meta/css/css-lists/counter-list-item-slot-order.html.ini`
`tests/wpt/meta/css/css-nesting/host-nesting-003.html.ini`
`tests/wpt/meta/css/selectors/is-where-shadow.html.ini`
and manual test in the below issue
The regression in
`tests/wpt/meta/html/rendering/the-details-element/details-blockification.html.ini`
has 1 more cause
https://github.com/servo/servo/pull/40977#issuecomment-3608471378

Fixes: [#40896](https://github.com/servo/servo/issues/40896)

cc: @xiaochengh

---------

Signed-off-by: batu_hoang <longvatrong111@gmail.com>
2025-12-04 05:57:34 +00:00
Oriol Brufau
2fdc18c48b script: Reconstruct box tree when order changes (#40994)
The CSS `order` property affects the order of boxes in the box tree.
Therefore, when it changes, we need to reconstruct it.

Testing: Adding new test
Fixes: #40813

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-12-02 06:57:05 +00:00
Martin Robinson
385a4bf64b script: Make a Layout-safe version of Element::each_custom_state (#40743)
`Element::each_custom_state` is called from Layout, but it creates
`DomRef` types on the stack, which can only be done on the main script
thread. Since layout might be doing styling and element consultation on
workers threads, expose a Layout-safe version of this change, which
doesn't have this issue.

Testing: This fixes two panics encountered during WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-12-01 22:33:27 +00:00
d-kraus
0a0a20a9c6 Replace some #[allow] with #[expect] (#40865)
Replaces some #[allow] with #[expect]. In case where the lint
expectation was unfulfilled, I removed it.


Testing: Refactor
Part of: https://github.com/servo/servo/issues/40383

Signed-off-by: Dennis Kraus <kraus@posteo.de>
2025-11-24 22:41:45 +00:00
Oriol Brufau
8b5333b38e layout: Cleanup for replaced elements with widgets (#40769)
This cleans up the changes done in #40578.

In particular, it removes the unnecessary `Contents::ReplacedWithWidget`
since we can handle that with `Contents::Replaced`. It also removes
`IndependentFormattingContextContents::ReplacedWithWidget` in favor of
`IndependentFormattingContextContents::Replaced`, by adding an optional
parameter for the widget.

That ensures that the behavior of replaced elements won't accidentally
diverge dependign on whether they have a widget. For example, #40578
forgot to handle `ReplacedWithWidget` in
`tentative_block_content_size()`.

Additionally, this removes the hardcoded especial behavior for `<video>`
that was added in `ServoThreadSafeLayoutElement::with_pseudo()`.

Testing: Adding a reftest
Fixes: #40708
Fixes: #40770

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-11-20 20:52:39 +00:00
Simon Wülker
c5da05348e script: Don't allocate when retrieving attribute values for layout (#40724)
We end up only calling `.iter` on these `Vec`s anyways.

Testing: No behaviour change intended, regressions are covered by
existing tests

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-18 19:13:26 +00:00
Martin Robinson
ffae4395fe layout: Rebuild the box tree when the quotes attribute changes on a pseudo-element (#40699)
In incremental layout, changes to the `quotes` attribute of a
pseudo-elment can cause the content of the pseudo-element to change so
should cause a box rebuild. This change does that, hopefully fixing
flaky tests.

Testing: This doesn't have any test changes, but should fix the test
situation described in #40419.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-11-18 08:04:07 +00:00
TIN TUN AUNG
6fda77da05 Media: Display User Agent Controls widget for video element. (#40578)
Add Contents::ReplacedWithWidget for video elements with UA control
widget, to allow Traverse into the children of video element during Box
Tree Construction, Generate
IndependentFormattingContextContent::ReplacedWithWidgets, to store both
the `ReplacedContents` and `BlockFormattingContext`. During fragment
tree generation process, first layout the Image Fragment, and then
Layout the Inner Controls BlockFormattingContext. Doing this allow us to
determine the size of Inner Controls widget based on the size of the
Image Fragment. Minor Fix: ::before/::after pseudo elment should be
suppress for replaced element.

Testing: Should show the controls widget for `<video controls></video>`,
and should not affect any existing WPT test. Since how to display UA
widget of Video Element is not defined in the spec, expectedly there has
no existing WPT test that testing this.
Fixes https://github.com/servo/servo/issues/40452
Fixes https://github.com/servo/servo/issues/31414

---------

Signed-off-by: rayguo17 <tin.tun.aung1@huawei.com>
2025-11-18 07:02:13 +00:00
Martin Robinson
8939240ed8 script: Trigger reflow properly for pseudo-elements with content: attr() (#40698)
When a Node with a pseudo-element style that uses `content: attr()`
has one of its attributes mutated, trigger a reflow starting at that
node. This is a crude implementation, because we currently aren't taking
into account what attributes changed, but at least it works.

Testing: This doesn't have any test changes, but should fix the test
situation described in #40419.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-11-17 23:18:41 +00:00
Oriol Brufau
1d0a8b05fb Upgrade Stylo to 2025-11-01 (#40522)
This continues #39612

Changelog:
- Upstream:
b98470a5cb...d71fd89b78
- Servo fixups:
4714bab122...7481d7f7af

Stylo tracking issue: https://github.com/servo/stylo/issues/264

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-11-11 02:59:38 +00:00
WaterWhisperer
241bff962d Change some #[allow]s to #[expect]s (#40458)
Removes some unneeded lints.

Testing: Refactor
Part of: #40383

Signed-off-by: WaterWhisperer <waterwhisperer24@qq.com>
2025-11-06 12:31:48 +00:00
Martin Robinson
f08460cded script: Handle broken image icon in HTMLImageElement (#40429)
Instead of having the `ImageCache` return the broken image icon for
failed loads, have `HTMLImageElement` explicitly request it. This means
that the image is loaded on demand (reducing the usage of resources) and
also simplifying the interface of the `ImageCache` greatly.

In addition, the display of the broken image icon is improved, more
closely matching other browsers. A test for this display (which was
falsely passing before) is updated to reflect the new display of the
broken image icon.

Testing: There is a Servo-specific test for this change. Some WPT tests
start to fail as well. Before these were not properly loading the broken
image icon so they were failing before, just in a hidden way.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-11-06 09:36:21 +00:00
Simon Wülker
c14795b33a Replace "map(..).unwrap_or(false)" with "is_some_and(..)" everywhere (#40244)
Testing: This change is a simple cleanup and should mostly be covered by
existing tests.

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-28 21:19:04 +00:00
Oriol Brufau
9264ef1a95 layout: Ensure IFC for abspos with inline-level original display (#39041)
Absolutely positioned elements get blockified, but their static position
still depends on the original display. Therefore, if we encounter an
abspos with an inline-level original display, we will now ensure that
it's handled in an inline formatting context. This way its static
position will correctly take into account things like `text-align`.

Testing: Several WPT tests are now passing.
Fixes: #39017

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-09-02 03:43:55 +00:00
Ashwin Naren
c92cd9e624 script: Move HTML DOM interfaces to script/dom/html/ (#39046)
See #38901.

Testing: Refactor
Fixes: Partially #38901

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
2025-08-31 01:00:09 +00:00
Simon Wülker
04dd74dddb script: Support custom element states (#38564)
Also adds support for `:state`.

Testing: Covered by existing tests

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-08-27 17:25:16 +00:00
webbeef
3225d19907 cargo: Bump rustc to 1.89 (#36818)
Update Rustc to 1.89.

Reviewable by commit.

Leftover work:
- #37330 
- #38777

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-08-19 11:07:53 +00:00
Martin Robinson
6fdf40dce7 layout: Always build Tag and BaseFragmentInfo with ServoThreadSafeLayoutNode (#38680)
This cleanup makes the interface a bit simpler and prevents problems
where the pseudo-element information is not passed by accident.

Testing: This should not change behavior, so is covered by existing
tests.

---------

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-18 12:19:09 +00:00
Martin Robinson
99ce81cf64 layout: Support storing layout data for two-level nested pseudo-elements (#38678)
Add basic support for storing layout data for pseudo-elements nested to
up to two levels. This removes the last unstored layout result and fixes
a double-borrow issue. This change does not add properly parsing nor
styling of these element types, but does prepare for those changes which
must come from stylo.

Testing: This fixes a intermittent panic in
`tests/wpt/tests/css/css-lists/nested-marker-styling.html`
Fixes: #38177. 
Closes: #38183.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-14 13:41:34 +00:00
Martin Robinson
5ff084a688 layout: Use the PseudoElement from ServoThreadSafeLayoutNode in NodeAndStyleInfo (#38630)
Instead of storing the non-pseudo version of the node in
`NodeAndStyleInfo`, store the pseudo version and use that to query the
`PseudoElement` that a `NodeAndStyleInfo` refers to.

This is a step on the way toward fixing nested pseudo-elements in Servo.

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

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-13 17:31:57 +00:00
Martin Robinson
ee7c1d9109 layout: Use ServoThreadSafeLayoutNode in more places (#38626)
Use `ServoThreadSafeLayoutNode` in more places in layout rather than
`ServoLayoutNode`. The former is meant to be used during layout, but
layout 2020 was written against the latter. In general, this reduces the
amount of conversion to the thread-safe version in many places in
layout.

In addition, an unused iterator from the `script` crate
`ServoThreadSafeLayoutNodeChildrenIterator` is replaced with the child
iterator from `layout`. The `layout` version must be directly in
`script` now as it uses the dangerous variants of `next_sibling` and
`first_child`, which allow encapsulating the unsafe bits into one
module.

This will ultimately be useful for storing the layout data of
pseudo-element children of pseudo-elements properly.

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

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-13 14:55:19 +00:00
Mukilan Thiyagarajan
4c05758ded script: support inline SVG by serializing the subtree (#38188)
This patch adds support for rendering static inline SVG documents in the
DOM tree by serializing the SVGElement's subtree and leveraging the
existing resvg based SVG stack for rendering. Serialiing the subtree is
necessary as resvg's tree representation (roxmltree) is immutable, so we
can't construct the tree incrementally.

Few other design choices here:
1. The `SVGSVGElement` is now treated as a replaced element and the
   layout code is responsible for plumbing the serialized SVG source
   (encoded as a base64 data: url) into the image cache, much like how
   background images are handled.
2. The serialization is done on the script thread after an initial
   layout pass. This is necessary because the serialization code asserts
that it is invoked from script thread i.e we can't call it from layout
   workers.
3. The serialized SVG data: url is cached to avoid recomputing it on
   subsequent layouts. The cache is invalidated when the SVGSVGElement's
   subtree is mutated.

The original SVGSVGElement code was behind the `dom_svg_enabled` pref.
This patch also removes the preference and make SVG support using resvg
available unconditionally.

Below is the analysis of the new test failures:

These tests use inline SVG but used to pass by accident.
They now fail because they contain SVG with no intrinsic
sizing which is not handled by resvg in a way that would
allows us to distinguish it from the sized case. The same
limitation applies to non-inline SVG.

 - /css/CSS2/positioning/absolute-replaced-width-003a.xht
 - /css/CSS2/positioning/absolute-replaced-width-003b.xht
 - /css/CSS2/positioning/absolute-replaced-width-003c.xht

These tests employ CSS styles in the HTML that
target the elements in inline SVG, which is not currently
supported.

-
/css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg-basic.html
 - /css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg.html

This is a tentative test that uses the unsupported 'border-shape' CSS
property. The ref uses SVG, so it used to pass accidentally. The ref
still doesn't render correctly since it also relies on styling SVG
elements using CSS classes in the HTML (instead of inline in SVG).

 - /css/css-borders/tentative/border-shape/border-shape-stroke.html

These tests use the attribute 'clip-path=circle(...)' in the
test, but this doesn't seem to work in resvg.

 - /css/css-masking/clip-path/clip-path-borderBox-1b.html
 - /css/css-masking/clip-path/clip-path-contentBox-1b.html
 - /css/css-masking/clip-path/clip-path-contentBox-1c.html
 - /css/css-masking/clip-path/clip-path-fillBox-1b.html
 - /css/css-masking/clip-path/clip-path-marginBox-1a.html
 - /css/css-masking/clip-path/clip-path-paddingBox-1b.html
 - /css/css-masking/clip-path/clip-path-strokeBox-1b.html
 - /css/css-masking/clip-path/clip-path-strokeBox-1c.html
 - /css/css-masking/clip-path/clip-path-viewBox-1a.html
 - /css/css-masking/clip-path/clip-path-viewBox-1b.html
 - /css/css-masking/clip-path/clip-path-viewBox-1d.html
 - /css/css-masking/clip-path/svg-clip-path-circle-offset.html
 - /css/css-masking/clip-path/svg-clip-path-ellipse-offset.html

Additionally, the below two tests use a `foreignObject` SVG element
which
embeds a html div fragment. This is also not supported by resvg.

 - /css/css-masking/clip-path/clip-path-viewBox-1d.html
 - /css/css-masking/clip-path/clip-path-fillBox-1b.html

The following test fails because of apparent pixel differences
between a circle rendered purely using CSS clip-path vs a circle
rendered in SVG using resvg.

 - /css/css-masking/clip-path/clip-path-contentBox-1c.html

These tests style the inline SVG elements using CSS in the HTML or
separate stylesheet. This is not supported by this implementation.

 - /css-transforms/document-styles/svg-document-styles-{001..004}.html
 - /css-transforms/document-styles/svg-document-styles-012.html
 - /css-transforms/external-styles/svg-external-styles-{001..004}.html
 - /css-transforms/external-styles/svg-external-styles-014.html

These tests seem like they should pass, but they fail because of what
seems like an anti-aliasing issue in the rendering engine. The
transformed element has a thin outline which is causing pixel difference
with the ref:

 - /css/css-transforms/group/svg-transform-group-008.html
 - /css/css-transforms/group/svg-transform-group-009.html
 - /css/css-transforms/group/svg-transform-nested-009.html
 - /css/css-transforms/group/svg-transform-nested-013.html
 - /css/css-transforms/group/svg-transform-nested-014.html
 - /css/css-transforms/group/svg-transform-nested-018.html
 - /css/css-transforms/group/svg-transform-nested-019.html
 - /css/css-transforms/group/svg-transform-nested-008.html

The below tests fail because resvg is calculating the wrong size for the
'rect' inside the SVG. The dimensions of the SVG are established via the
CSS in the HTML, so it seems resvg is using incorrect coordinates for
the children of the svg when explict width/height are not specified in
the root svg element.

 - /css/css-transforms/group/svg-transform-group-011.html
 - /css/css-transforms/group/svg-transform-nested-021.html
 - /css/css-transforms/group/svg-transform-nested-029.html

All these tests use an SVG that doesn't have width nor height attributes
and this causes resvg to use incorrect coordinates for the SVG's
children. In addition, the following tests use the CSS syntax for
transforms inside the SVG (using style attribute) which is not supported
by resvg (it only supports the SVG 1.1 transform syntax).

 - /css/css-transforms/inline-styles/svg-inline-styles-{001..004}.html
 - /css/css-transforms/inline-styles/svg-inline-styles-012.html

In the case of these four tests, the `style` attribute specifies an
invalid transform, but resvg doesn't fallback to the transform specified
via the `transform`  attribute on the same element.

 - /css/css-transforms/inline-styles/svg-inline-styles-005.html
 - /css/css-transforms/inline-styles/svg-inline-styles-006.html
 - /css/css-transforms/inline-styles/svg-inline-styles-010.html
 - /css/css-transforms/inline-styles/svg-inline-styles-013.html

The following test fails because of the lack of width/height in SVG as
described above but it also exposes gaps in our CSS tranform
implementation.

 - /css/css-transforms/preserve3d-and-filter-with-perspective.html

These tests failure because resvg doesn't handle the SVG without
explicit width and height, but specified via CSS in the HTML. In
addition, there are pixel differences between the ref due to
antialiasing issues.

 - /css/css-transforms/matrix/svg-matrix-{005...008}.html
 - /css/css-transforms/matrix/svg-matrix-010.html
 - /css/css-transforms/matrix/svg-matrix-012.html
 - /css/css-transforms/matrix/svg-matrix-{015..069}.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-001.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-011.html
 - /css/css-transforms/rotate/svg-rotate-angle-45-022.html
 - /css/css-transforms/scale/svg-scale-006.html
 - /css/css-transforms/scale/svg-scale-007.html

These tests seem to be failing due to some sort of antialiasing issue,
where a transformed SVG element has a thin border that causes pixel
differences compared to the solid colored reference.

 - /css/css-transforms/skewX/svg-skewx-001.html
 - /css/css-transforms/skewX/svg-skewx-006.html
 - /css/css-transforms/skewX/svg-skewx-011.html
 - /css/css-transforms/skewX/svg-skewx-016.html
 - /css/css-transforms/skewX/svg-skewx-021.html
 - /css/css-transforms/skewX/svg-skewxy-001.html
 - /css/css-transforms/skewY/svg-skewy-001.html
 - /css/css-transforms/skewY/svg-skewy-006.html
 - /css/css-transforms/skewY/svg-skewy-011.html
 - /css/css-transforms/skewY/svg-skewy-016.html
 - /css/css-transforms/skewY/svg-skewy-021.html

These tests specify several SVG attributes such as transform,
vector-effect etc via CSS in the HTML (rather than inline in SVG). The
current implementation doesn't support this.

 - /css/css-transforms/transform-box/stroke-box-mutation-001.html
 - /css/css-transforms/transform-box/stroke-box-mutation-002.html
 - /css/css-transforms/transform-box/stroke-box-mutation-003.html
 - /css/css-transforms/transform-box/stroke-box-mutation-004.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-002.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-003.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-004.html
 - /css/css-transforms/transform-box/svgbox-stroke-box-005.html

These tests depend on 'transform-origin' specified on an element inside
an SVG, but this transform is influenced by the 'tranform-box' set via
CSS in the HTML itself (not the SVG). The current implementation doesn't
support styling the SVG using document styles, so these tests just fail.

- /css/css-transforms/transform-origin/svg-origin-relative-length-*.html

These tests check the fallback behaviour when invalid syntax is
encountered in the 'transform-origin' value. resvg doesn't correctly
fallback to 0,0 causing the tests to fail.

-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html
-
/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html

These tests use unimplemented Canvas APIs like 'beginLayer' and
the 'CanvasFilter' constructor and hence fail at runtime.

-
/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
-
/html/canvas/element/filters/2d.filter.layers.gaussianBlur.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.tentative.html
-
/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.tentative.html
-
/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.tentative.html
 - /html/canvas/element/layers/2d.layer.css-filters.blur.tentative.html
- /html/canvas/element/layers/2d.layer.css-filters.shadow.tentative.html
 - /html/canvas/element/layers/2d.layer.ctm.layer-filter.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.tentative.html
-
/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.isotropic.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-x.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.mostly-y.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.x-only.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.anisotropic-blur.y-only.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.css-filters.blur-and-shadow.tentative.html
- /html/canvas/offscreen/layers/2d.layer.css-filters.blur.tentative.html
-
/html/canvas/offscreen/layers/2d.layer.css-filters.shadow.tentative.html
- /html/canvas/offscreen/layers/2d.layer.ctm.layer-filter.tentative.html

These tests fail because resvg doesn't seem to honour the 'translate'
CSS property specified on an SVG element using an inline 'style'
attribute.

 - /css/css-transforms/translate/svg-translate-with-units.html
-
/css/css-transforms/translate/translate-and-transform-attribute-in-svg.html
-
/css/css-transforms/translate/translate-and-transform-css-property-in-svg.html
 - /css/css-transforms/translate/translate-in-svg.html

These tests seem to fail due to the filter effect implementation in
resvg either not being complete or spec compliant.

 - /css/filter-effects/feconvolve-divisor.html
 - /css/filter-effects/feconvolve-region-001.html
 - /css/filter-effects/feconvolve-region-002.html
 - /css/filter-effects/filter-subregion-01.html
 - /css/filter-effects/svg-feimage-002.html
 - /css/filter-effects/svg-feimage-003.html
 - /css/filter-effects/svg-feimage-004.html
 - /css/filter-effects/svg-feoffset-001.html

The test /css/filter-effects/svg-feimage-004.html should ideally PASS
but currently fails because we don't propagate height/width set using
CSS in HTML element to the root SVG, so resvg uses the wrong dimensions
when rendering the children of the SVG.

These failures are due to deficienies in our current implementation
i.e we don't support styling SVG elements using CSS in HTML.

-
/css/css-transforms/gradientTransform/svg-gradientTransform-combination-001.html
 - /css/selectors/sharing-in-svg-use.html

The below test fails as our current implementation relies on resvg to
tell us the intrinsic ratio of the SVG, but this doesn't always work
correctly.

 - /css/css-sizing/svg-intrinsic-size-005.html

This failure is due to lack of proper fallback to no-op transform in
resvg when the `rotate()` syntax is specified with an invalid list e.g
`rotate(90,)`.

 - /css/css-transforms/rotate/svg-rotate-3args-invalid-002.html

This test only passes in CI and based on the raw log output, it seems
that no text inside the SVG is rendered in the CI. This could be an font
stack related issue.

 - /css/css-display/display-contents-svg-elements.html

This test asserts that the CSP blocks loads triggered using `use`
elements in SVG. It used to TIMEOUT as without inline SVG support, no
CSP violation event was triggered. It fails now since the event is now
triggered for the load of the SVG itself (our current implementation
loads inline SVGs as serialized base64 data: urls). This doesn't match
the blocked URL in the use element though.

 - /content-security-policy/img-src/svg-use-blocked.tentative.html

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-08-11 11:07:59 +00:00
JoeDow
9ef4d0c9d7 layout: Correctly marking box damage when text-related style changed (#38059)
This change aims to supplement the missing incremental box tree
construction when text-related styles change. Since certain text style
adjustments can alter visible text content and typography. Therefore,
the parent nodes of such text are marked as needing to re-collect their
box tree children to ensure the correct display of text.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
2025-07-26 11:50:13 +00:00
Jo Steven Novaryo
3cb16eb864 Reland Input type=text Shadow DOM With Performance Improvement (#37483)
Depends on #37427.

In addition to the changes introduced by
https://github.com/servo/servo/pull/37065, there are several performance
improvements and nits as follows:
- Use the internal pseudo element for style matching, this will reduce
the performance regression by ~66%.
- Manual construction of the `Text` node inside a text container. This
is followed by the modification of the inner `Text` node instead of
using `SetTextContent` which is more expensive.
- Use `implemented_pseudo_element` instead of
`text_control_inner_editor` `NodeFlag` to handle the special cases that
these elements should follow, specifically the:
  - focus delegation workaround;
  - selections; and
  - line height resolving.
- More documentation.

Servo's side of: https://github.com/servo/stylo/pull/217

Testing: No new unexpected WPT failure, except for the one introduced by
https://github.com/servo/servo/pull/37065/.
Fixes: #36307 #37205

---------

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
2025-07-23 09:08:24 +00:00
Martin Robinson
2366a8bf9e script: Wrapping unsafe code in unsafe blocks for basic DOM types (#37997)
There is a new default cargo clippy lint, `unsafe_op_in_unsafe_fn`,
which requires unsafe code to be wrapped in unsafe blocks, even inside
functions marked as unsafe. The lint is disabled as much of our code
doesn't fulfill this contract. The thing itself is pretty useful in
order to gradually remove unsafety, so this change starts adding
`unsafe` blocks so we can eventually enable this lint.

Testing: This doesn't change behavior so existings tests should suffice.
Fixes: This is part of #35955.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-07-11 11:38:02 +00:00
Martin Robinson
436c9072c4 layout: Skip box tree construction when possible (#37957)
When a style change does not chang the structure of the box tree, it is
possible to skip box tree rebuilding for an element. This change adds
support for reusing old box trees when no element has that type of
damage. In order to make this happen, there needs to be a type of
"empty" `LayoutDamage` that just indicates that a fragment tree layout
is necessary.

This is the first step toward incremental fragment tree layout.

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

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-07-09 17:33:09 +00:00
Steven Novaryo
378c4648e4 script: Use an implemented pseudo-element to fortype=color ::color-swatch (#37427)
Implement internal pseudo element, which would be resolved as a
"Implemented Pseudo Element" within style computation. This is an
concrete element that would has a primary style after the style
computation, but could match and style resolved like an pseudo element.
Therefore, it would have a different behavior compared to how does
`pseudo`s that `ServoLayoutNode` had. Where they would not have a
concrete element behind it. Note that, due to the nature of these pseudo
elements residing inside a UA widget, these pseudo elements would
therefore not be accessible in JavaScript by default.

This kind of element is required in order to implement the [form control
pseudo element](https://drafts.csswg.org/css-forms-1/#pseudo-elements)
like `::placeholder`, `::color-swatch`, `::field-text`, etc.
 
See [this docs](https://hackmd.io/@ChaKweTiau/BJ3zRdLQlg) for more
details of the implementation.

Then, the implemented pseudo element is utilized to implement style
matching for input `type=text`.

Servo's side of: https://github.com/servo/stylo/pull/212

Testing: No WPT regression.

---------

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
2025-07-09 15:36:58 +00:00
Martin Robinson
5286869b96 layout: Start using the new extensible RestyleDamage type from Stylo (#37592)
This will allow Servo to add custom types of damage in the near future
which correspond to minor phases layout. The damage exposed by Stylo
only corresponds to the major layout phses. In the future, both phases
will likely be managed by Servo itself and implementors will need to
provide their own damage system entirely.

Testing: This shouldn't change behavior and thus is covered by existing
tests.

Stylo PR: https://github.com/servo/stylo/pull/207

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-06-26 14:10:48 +00:00
Martin Robinson
69ff4afa58 Rename script_layout_interface to layout_api (#37591)
Now that we are standardizing on the `_traits` crates becoming `_api`
and exposing the API of the crate that they get their name from [^1],
`script_layout_interface` becomes `layout_api` as it exposes the API for
`layout` that is used by `script` This brings the crate in line with the
naming of the other ones in `shared`.

[^1]:
https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Organizing.20*_traits.20crates/with/396893711

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

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-06-20 17:13:05 +00:00
Simon Wülker
6cac782fb1 Support exporting shadow parts with the exportparts attribute (#37345)
The attribute is implemented as a new `AttrValue` variant containing the
mappings of exported part names
(https://github.com/servo/stylo/pull/197).

Take a look at the [MDN
page](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/exportparts)
for more information about the attribute.


Testing: Covered by WPT
Fixes: https://github.com/servo/servo/issues/35349

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-06-13 11:32:20 +00:00
Simon Wülker
0fa3de3937 Support ::part selector (#37307)
This is pretty much just wiring up the necessary stylo methods. Note
that the `exportparts` attribute is not yet supported, I'll do that in a
followup change

Testing: Covered by existing web platform tests.
This is the first half of https://github.com/servo/servo/issues/35349

Fixes https://github.com/servo/servo/issues/37325

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-06-09 10:17:28 +00:00
webbeef
a1f43ab06d Revert "Implement Input UA Shadow DOM (#37065)" (#37296)
This reverts commit 5580704438.

Let's re-land that fix when a working solution is found. Keeping that
regression makes it hard to evaluate other potential improvements.

Signed-off-by: webbeef <me@webbeef.org>
2025-06-06 15:23:08 +00:00
Steven Novaryo
5580704438 Implement Input type=text UA Shadow DOM (#37065)
Implement Shadow Tree construction for input `type=text`, adding a text
control inner editor container and placeholder container. Subsequently,
due to the changes of the DOM tree structure, the changes will add a new
NodeFlag `IS_TEXT_CONTROL_INNER_EDITOR` to handle the following cases.
- If a mouse click button event hits a text control inner editor, it
will redirect the focus target to its shadow host.
- In text run's construction, the text control inner editor container
queries the selection from its shadow host. This is later used to
resolve caret and selection painting in the display list.

This will be the first step of fixing input `type=text` and other
single-line text input element widgets. Such as, implementing
`::placeholder` selector.



Testing: Existing WPT test and new Servo specific appearance WPT.
Fixes: #36307

---------

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
2025-05-30 12:02:10 +00:00
Mukilan Thiyagarajan
8a20e42de4 Add support for static SVG images using resvg crate (#36721)
This change adds support for rendering static SVG images using the
`resvg` crate, allowing svg sources in the `img` tag and in CSS
`background` and `content` properties. There are some limitations in
using resvg:

1. There is no support for animations or interactivity as these would
require implementing the full DOM layer of SVG specification.
2. Only system fonts can be used for text rendering. There is some
mechanism to provide a custom font resolver to usvg, but that is not
explored in this change.
3. resvg's handling of certain edge cases involving lack of explicit
`width` and `height` on the root svg element deviates from what the
specification expects from browsers. For example, resvg uses the values
in `viewBox` to derive the missing width or height dimension, but
without scaling that dimension to preserve the aspect ratio. It also
doesn't allow overriding this behavior.

Demo screenshot:
![servo - resvg
img](https://github.com/user-attachments/assets/8ecb2de2-ab7c-48e2-9f08-2d09d2cb8791)

<details>
<summary>Source</summary>

```
<style>
 #svg1 {
   border: 1px solid red;
 }

 #svg2 {
   border: 1px solid red;
   width: 300px;
 }
 #svg3 {
   border: 1px solid red;
   width: 300px;
   height: 200px;
   object-fit: contain;
 }
 #svg4 {
   border: 1px solid red;
   width: 300px;
   height: 200px;
   object-fit: cover;
 }
 #svg5 {
   border: 1px solid red;
   width: 300px;
   height: 200px;
   object-fit: fill;
 }
 #svg6 {
   border: 1px solid red;
   width: 300px;
   height: 200px;
   object-fit: none;
 }
</style>
</head>
<body>
        <div>
          <img id="svg1" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
        </div>
        <div>
          <img id="svg2" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
          <img id="svg3" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
          <img id="svg4" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
        </div>
        <div>
          <img id="svg5" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
          <img id="svg6" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
        </div>
</body>
```

</details>

---------

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2025-05-27 11:02:40 +00:00
Simon Wülker
b100a98e1d Fully support <input type=color> (#36992)
This change adds a shadow-tree widget for `<input type=color>` elements.
It also involves some changes to the way layout interacts with the DOM,
because currently all `input` and `textarea` elements are rendered as
plain text and their descendants are ignored. This obviously doesn't
work for `<input type={color, date, range, etc}>`.


![image](https://github.com/user-attachments/assets/4f16c3b0-1f79-4095-b19d-1153f5853dd5)

<details><summary>HTML used for the screenshot above</summary>

```html
<input type=color>
```

</details>



Testing: I doubt that this affects WPT tests, because the appearance and
behaviour of the widget is almost entirely unspecified.

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-05-15 17:30:38 +00:00
Nico Burns
c792e6db7c Use version of markup5ever with web_atoms crate (#36542)
Upgrades `markup5ever` and fixes "unnecessary import" lints.

See https://github.com/servo/html5ever/pull/599
And https://github.com/servo/stylo/pull/173

Signed-off-by: Nico Burns <nico@nicoburns.com>
2025-04-19 11:49:37 +00:00