26 Commits

Author SHA1 Message Date
Jonathan Schwender
eac6ff8509 Metadata: Add missing repository information (#43451)
This fixes a warning of `cargo publish`: 

```
warning: manifest has no description, documentation, homepage or repository
```

Testing: Compiling. Manual testing of `cargo publish --dry-run` (with
some additional patches, and until the next error, shows this warning
has been fixed)

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2026-03-19 08:54:18 +00:00
Simon Wülker
c0ff7c1fc9 Everywhere: Remove instances of clippy::redundant-clone (#43212)
This change fixes all instances where
[`clippy::redundant-clone`](https://rust-lang.github.io/rust-clippy/master/index.html?groups=complexity%2Ccorrectness%2Cnursery%2Csuspicious&levels=allow#redundant_clone)
would trigger. It's allowed by default

I've also changed the lint to warn-by-default for servo.

Testing: Covered by WPT

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2026-03-12 13:28:21 +00:00
Jonathan Schwender
37dfa42731 Unify servo package naming (#42916)
This is a preparation for publishing to crates.io. Changes include:
- Add `servo-` prefixes to avoid name collisions on crates.io
- Use `-` instead of `_` in package names.
- Rename the crates to their original names in Cargo.toml,
  to keep the diff minimal
- Rename `media` to `servo-media-thread` to avoid name collision with
  `servo-media` (originally from the media repository).

This is an outcome of the previous discussion at [#general > Switch
remaining git dependencies to
crates.io](https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Switch.20remaining.20git.20dependencies.20to.20crates.2Eio/with/576336288)

Testing: This should be mostly covered by our CI, but some amount of
breakage is to be expected, since some package names could still be
referenced from scripts which are not tested or run in CI. [mach try
run](https://github.com/jschwe/servo/actions/runs/22502945949)

---------

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2026-03-01 14:15:27 +00:00
Ignacio Casal Quinteiro
b00a76427a Fix various typos throughout the code base (#40934)
Signed-off-by: Ignacio Casal Quinteiro <qignacio@amazon.com>
2025-11-28 15:00:56 +00:00
Simon Wülker
e914e76b08 xpath: Handle a NodeSet being passed to id (#40593)
When a NodeSet is passed to the `id` function then we want to act as if
we were computing the union of individual `id` calls for each node in
the set. We weren't doing that before.

Depends on https://github.com/servo/servo/pull/40592
Testing: A new test starts to pass

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-13 18:13:12 +00:00
Simon Wülker
c039078ab3 xpath: Apply predicate list before sorting result when evaluating location step expression (#40592)
The result of a predicate can depend on the position of the node in its
set, and this position is dependent on the axis that the node set came
from. This is specified in
https://www.w3.org/TR/1999/REC-xpath-19991116/#predicates.

Additionally, this change fixes a small bug in the implementation of
`preceding::` (https://github.com/servo/servo/pull/40588) where the root
of a subtree would be included twice. That wasn't discovered earlier
because nodes are deduplicated at the end of the evaluation.

Testing: New tests start to pass, this change adds more tests

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-13 10:27:06 +00:00
Simon Wülker
5ecf09d76a xpath: Fix implementation for preceding::/following:: axes (#40588)
`preceding::` needs to yield all preceding nodes, excluding ancestors.
`following::` needs to yield all following nodes, excluding descendants.

Both `Node::preceding_nodes` and `Node::following_nodes` (which we're
currently using) don't quite match these requirements, so we have to
engineer some xpath-specific iterators.

Testing: New tests start to pass

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-12 10:40:36 +00:00
Simon Wülker
bcba86eef7 xpath: Cleanup normalize-space and translate (#40566)
`translate` was incorrect in numerous ways before, so this change
completely replaces it.


Testing: This change adds a couple unit tests, a new xpathmark-ft test
starts to pass

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-12 08:24:26 +00:00
Simon Wülker
7e59627407 xpath: Don't expect ancestor-or-self axis to be in tree order (#40542)
Depends on https://github.com/servo/servo/pull/40541

We still don't really pass any tests because we incorrectly compare
local names case-sensitively. Needs more investigation.

Testing: New tests start to not-crash
Fixes https://github.com/servo/servo/issues/40540

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-11 13:09:17 +00:00
Simon Wülker
9193b1d310 xpath: Enforce tree order in node sets during evaluation (#40451)
This change adds `NodeSet`, which is more or less a `Vec<Node>` that
knows whether it is sorted, and can sort itself if it isn't. This allows
us to efficiently enforce tree order in intermediary node sets that
occur during evaluation.

Notably, in many cases it is not necessary to sort at all, because all
location step expressions yield node sets that are either already sorted
(`Axis::DescendantOrSelf` for example), or that are in inverse tree
order (`Axis::PrecedingSiblings` for example).

There's still optimization work left to be done. When merging two node
sets that are already sorted then we could use merge sort instead of
appending one to the other and naively sorting. But I suspect that the
sorting algorithm used by the standard library is already well tuned to
handle such cases...

Testing: This change adds a web platform test
Fixes https://github.com/servo/servo/issues/40435

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-06 12:24:07 +00:00
Simon Wülker
dc3e57f9a7 xpath: Handle OOB conditions and non-char-boundaries in substring (#40411)
This change fixes two panics and cleans up a bunch of the surrounding
code.

Testing: I've added new unit tests

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-11-04 22:03:22 +00:00
Simon Wülker
d3fd90b916 xpath: Throw a NAMESPACE_ERR DOMException when namespace resolver callback returns invalid value or throws (#40167)
I always thought that exceptions thrown in namespace resolver callbacks
should be propagated to the call site of `document.evaluate`.
That is not the case - the exception is silently swallowed and you get a
namespace error, the same as if the callback had returned any other
invalid value.

Testing: New web platform tests start to pass
Fixes https://github.com/servo/servo/issues/39931
Part of #34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-27 07:31:28 +00:00
Simon Wülker
ada2efd7d6 xpath: Compare local names in html documents case-insensitively when there's no prefix (#40161)
Relevant gecko code:
https://searchfox.org/firefox-main/rev/16707ce1df112d9e067175ed8e16be717ab684c4/dom/xslt/xpath/txExprParser.cpp#839.

Testing: New tests start to pass
Part of #34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-25 23:25:01 +00:00
Simon Wülker
26692ba732 xpath: Remove JS exception variant from evaluation error enum (#40164)
JS exceptions can't happen while evaluating an xpath expressions since
the namespace resolver callback is invoked during parsing.

Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-25 13:45:18 +00:00
Simon Wülker
74859780f1 xpath: Replace nom with hand-written parsing rules (#39977)
The new parser is more verbose, but also more correct and easier to
reason about. Apologies for the size of the change, I don't think
there's an alternative to swapping out the entire parser at once.

Testing: Covered by existing tests, new tests also start to pass
Fixes https://github.com/servo/servo/issues/38552
Fixes https://github.com/servo/servo/issues/38553
Fixes https://github.com/servo/servo/issues/39596
Closes https://github.com/servo/servo/issues/39602
Part of https://github.com/servo/servo/issues/34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-25 03:23:02 +00:00
Simon Wülker
a417dc5f23 xpath: Don't panic in node name test when namespace prefix is unknown (#39952)
We don't need to care about namespace prefixes in name tests because
they are already resolved to namespaces at this point.

The old implementation was also masking a few other small bugs which
I've fixed here. When the namespace resolver doesn't give us any results
then we should not lookup the namespace on the node itself. In XPath,
namespaces on html elements in html documents are compared a in a
relaxed way, and we were previously also using the relaxed comparison
mode on non-html elements in html documents (like svg).

Testing: Existing tests continue to pass (and the web platform tests
contain numerous namespace tests which cover this behaviour)
Fixes https://github.com/servo/servo/issues/39939
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-18 07:14:37 +00:00
Simon Wülker
01641b2374 xpath: let absolute path expressions begin at the root node (#39965)
Testing: This change adds a test
Fixes #39964
Part of https://github.com/servo/servo/issues/34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-17 18:11:53 +00:00
Simon Wülker
84d30339b5 xpath: Cast query result to desired type (#39764)
When running an XPath query, users supply a target result type (eg
`XPathResult.NUMBER_TYPE`). When this type does match the return value
of the query, then we need to convert to it.

See
https://searchfox.org/firefox-main/rev/ab5bf2401717970560597083d6ac72915bde2d89/dom/xslt/xpath/XPathResult.cpp#160
for the relevant part in gecko.

Testing: This change adds a test
Part of #34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-13 13:20:55 +00:00
Simon Wülker
e1c418d8b2 XPath: Flatten the AST to make it more flexible (#39800)
The current XPath AST is tightly tied to the parser grammar. To address
issues like https://github.com/servo/servo/issues/39739, we'll want to
do optimization passes on the AST in the future, which requires relaxing
it's structure first.

This PR moves the AST structure into a separate module and flattens it
into a shape where most expressions are variants of the core
`Expression` enum.

This also has the nice side effect of being a net reduction in LoC and
making the AST *significantly* easier to read.

I think the difference between the old and new structure is best
explained by example.
One of our unit tests parses `concat('hello', ' ', 'world')`, and the
current AST looks like this:

```rust
Expr::Path(PathExpr {
    is_absolute: false,
    is_descendant: false,
    steps: vec![StepExpr::Filter(FilterExpr {
        primary: PrimaryExpr::Function(CoreFunction::Concat(vec![
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(
                        "hello".to_string(),
                    )),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(" ".to_string())),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(
                        "world".to_string(),
                    )),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
        ])),
        predicates: PredicateListExpr { predicates: vec![] },
    })],
}),
```
After this change, the AST looks like this:
```rust
Expression::Function(CoreFunction::Concat(vec![
    Expression::Literal(Literal::String("hello".to_string())),
    Expression::Literal(Literal::String(" ".to_string())),
    Expression::Literal(Literal::String("world".to_string())),
])),
```

Testing:  No behaviour change intended, covered by existing tests.
Part of #34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-12 08:17:40 +00:00
Simon Wülker
77502dc076 xpath: Clean up the expression AST a bit (#39788)
The current AST has different nodes for additive, multiplicative,
relational (etc) expressions. That is not a useful distinction, as they
are all treated more or less the same. Instead, I've unified these as
`Expression::Binary(lhs, binary_operator, rhs)`.

There are also some silly things that can be removed, like
```rust
enum UnaryOp {
    Minus
}
```
This change is in preparation for an upcoming PR which will address
#39602 .


Testing:  Covered by existing tests
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-11 12:45:17 +00:00
Simon Wülker
dd036852a2 xpath: Avoid allocating hashmap when comparing NodeSet and String (#39774)
A NodeSet and a String are equal iff the text content of any node in the
set is equal to the string. Instead of creating a hashmap of text
contents and then calling `contains` on that, just iterate over the
nodeset and see if the string is in there.

Testing: This should not change behaviour and is thus covered by
existing tests
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-10 18:56:33 +00:00
Simon Wülker
f30bcde743 xpath: Reject non-ascii whitespace when converting string to number (#39746)
The `number` function converts from arbitrary values to numbers. String
values are parsed as you would expect, and whitespace around them is
trimmed. We used to allow arbitrary whitespace, firefox allows only
ASCII. I've taken this opportunity to also implement a dummy DOM that we
can use for testing these kinds of things.

Testing: This change adds new tests
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-10 11:32:52 +00:00
Simon Wülker
8a95283e87 xpath: Remove PredicateExpr (#39762)
A predicate expression is just a regular expressions. We can remove it
and make the AST a bit smaller (and easier to read).

Testing: Covered by existing tests
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-10 11:29:27 +00:00
Simon Wülker
a8f92f7fd2 xpath: Prove that some internal errors are unreachable (#39727)
The `Evaluatable` trait is used for enforcing a common interface for
expressions. Removing it allows us to pass additional parameters to some
functions that need them, which proves that a few errors are impossible
to reach.

Testing: Covered by existing tests
Part of #34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-09 23:45:09 +00:00
Simon Wülker
5510ea91b3 xpath: Remove XML QName validation (#39594)
*Most* of the properties that were verified here were already verified
by the xpath parser before. I have not found any evidence that other
browsers do the remaining checks. There are web platform tests that
expect contradicting behavior (which pass in other browsers).

Additionally, this change switches `xpath` to use `markup5ever` instead
of `html5ever` - this is a drop-in replacement. I thought I did this as
part of https://github.com/servo/servo/pull/39546 but apparently the
change got lost in the rebasing.


Testing: A new web platform test starts to pass.
Fixes https://github.com/servo/servo/issues/39442
Part of #34527

cc @minghuaw

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-01 07:41:56 +00:00
Simon Wülker
e5017b1b50 Move XPath implementation into its own crate (#39546)
XPath (and, in the future, XSLT) is only loosely coupled to `script`. As
`script` is already very large, I'd like to move the xpath parser and
evaluator into a seperate crate. Doing so allows us to iterate on it
more easily, without having to recompile `script`. Abstracting over the
concrete DOM implementation could also allow us to write some more
comprehensive unit tests.

Testing: Covered by existing web platform tests
Part of https://github.com/servo/servo/issues/34527
Fixes https://github.com/servo/servo/issues/39551

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-09-30 19:55:10 +00:00