Add XPath parser/evaluator (#34463)

* Add XPath parser/evaluator

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* Correctly annotate XPathEvaluator IDL

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: have bindings pass in `can_gc`

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: add docstrings

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: implement PartialEq for Value for readability

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: add docstrings for CoreFunctions

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: simplify node test code

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: add unit tests for string handling xpath functions

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* put xpath features behind dom.xpath.enabled pref

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review] remove rstest and insta dev-deps

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* update wpt test expectations

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* [PR review]: tweak metadata files

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

* update wpt test expectations AGAIN

Signed-off-by: Ville Lindholm <ville@lindholm.dev>

---------

Signed-off-by: Ville Lindholm <ville@lindholm.dev>
This commit is contained in:
Ville Lindholm 2024-12-08 04:01:50 +02:00 committed by GitHub
parent 264c0f972f
commit bc7fe41a02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 6426 additions and 314 deletions

View file

@ -131,6 +131,8 @@ skip: true
skip: false
[domparsing]
skip: false
[domxpath]
skip: false
[encoding]
skip: false
[eventsource]

View file

@ -1 +1 @@
prefs: ["dom.imagebitmap.enabled:true", "dom.offscreen_canvas.enabled:true", "dom.shadowdom.enabled:true"]
prefs: ["dom.imagebitmap.enabled:true", "dom.offscreen_canvas.enabled:true", "dom.shadowdom.enabled:true", "dom.xpath.enabled:true"]

View file

@ -1,39 +1,15 @@
[idlharness.window.html?include=Node]
[idl_test setup]
expected: FAIL
[idlharness.window.html?exclude=Node]
[XPathExpression interface: document.createExpression("//*") must inherit property "evaluate(Node, optional unsigned short, optional XPathResult?)" with the proper type]
expected: FAIL
[XPathResult interface: attribute singleNodeValue]
expected: FAIL
[XPathResult interface object name]
expected: FAIL
[Element interface: operation replaceWith((Node or DOMString)...)]
expected: FAIL
[Document interface: operation createNSResolver(Node)]
expected: FAIL
[Document interface: operation prepend((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "snapshotLength" with the proper type]
expected: FAIL
[XPathEvaluator interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[AbortSignal must be primary interface of new AbortController().signal]
expected: FAIL
[XPathResult interface: constant NUMBER_TYPE on interface object]
expected: FAIL
[Element interface: element must inherit property "assignedSlot" with the proper type]
expected: FAIL
@ -46,9 +22,6 @@
[Event interface: attribute composed]
expected: FAIL
[XPathResult interface: constant STRING_TYPE on interface object]
expected: FAIL
[Text interface: attribute assignedSlot]
expected: FAIL
@ -61,12 +34,6 @@
[AbortSignal interface: existence and properties of interface object]
expected: FAIL
[XPathResult interface: constant STRING_TYPE on interface prototype object]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "ORDERED_NODE_ITERATOR_TYPE" with the proper type]
expected: FAIL
[EventTarget interface: calling removeEventListener(DOMString, EventListener?, optional (EventListenerOptions or boolean)) on new AbortController().signal with too few arguments must throw TypeError]
expected: FAIL
@ -82,66 +49,27 @@
[Event interface: new CustomEvent("foo") must inherit property "composed" with the proper type]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "UNORDERED_NODE_ITERATOR_TYPE" with the proper type]
expected: FAIL
[EventTarget interface: new AbortController().signal must inherit property "removeEventListener(DOMString, EventListener?, optional (EventListenerOptions or boolean))" with the proper type]
expected: FAIL
[Document interface: xmlDoc must inherit property "createNSResolver(Node)" with the proper type]
expected: FAIL
[XPathResult interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[XPathEvaluator interface: operation createExpression(DOMString, optional XPathNSResolver?)]
expected: FAIL
[AbortController interface: operation abort()]
expected: FAIL
[AbortController interface: existence and properties of interface object]
expected: FAIL
[XPathResult interface: constant UNORDERED_NODE_ITERATOR_TYPE on interface prototype object]
expected: FAIL
[Element interface: operation prepend((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "ANY_UNORDERED_NODE_TYPE" with the proper type]
expected: FAIL
[AbortController interface: attribute signal]
expected: FAIL
[XPathResult interface: constant UNORDERED_NODE_SNAPSHOT_TYPE on interface prototype object]
expected: FAIL
[XPathResult interface: constant ORDERED_NODE_SNAPSHOT_TYPE on interface object]
expected: FAIL
[XPathResult interface: constant ANY_TYPE on interface prototype object]
expected: FAIL
[CharacterData interface: operation before((Node or DOMString)...)]
expected: FAIL
[AbortSignal interface: attribute aborted]
expected: FAIL
[XPathResult interface: operation snapshotItem(unsigned long)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "ANY_TYPE" with the proper type]
expected: FAIL
[XPathEvaluator interface: operation evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?)]
expected: FAIL
[XPathResult interface: existence and properties of interface object]
expected: FAIL
[Element interface: operation after((Node or DOMString)...)]
expected: FAIL
@ -154,51 +82,18 @@
[Element interface: attribute assignedSlot]
expected: FAIL
[XPathEvaluator interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[XPathExpression interface: existence and properties of interface prototype object]
expected: FAIL
[XPathResult interface: constant ORDERED_NODE_ITERATOR_TYPE on interface object]
expected: FAIL
[CharacterData interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[CharacterData interface: operation remove()]
expected: FAIL
[XPathEvaluator interface: existence and properties of interface object]
expected: FAIL
[XPathResult interface: calling snapshotItem(unsigned long) on document.evaluate("//*", document.body) with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "snapshotItem(unsigned long)" with the proper type]
expected: FAIL
[Element interface: element must inherit property "slot" with the proper type]
expected: FAIL
[Document interface: new Document() must inherit property "evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?)" with the proper type]
expected: FAIL
[Document interface: xmlDoc must inherit property "evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?)" with the proper type]
expected: FAIL
[XPathExpression interface: operation evaluate(Node, optional unsigned short, optional XPathResult?)]
expected: FAIL
[AbortController interface: new AbortController() must inherit property "signal" with the proper type]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "iterateNext()" with the proper type]
expected: FAIL
[Document interface: calling createNSResolver(Node) on new Document() with too few arguments must throw TypeError]
expected: FAIL
[ShadowRoot interface: attribute onslotchange]
expected: FAIL
@ -208,234 +103,72 @@
[Element interface: attribute slot]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "invalidIteratorState" with the proper type]
expected: FAIL
[DocumentType interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[Document interface: calling evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?) on new Document() with too few arguments must throw TypeError]
expected: FAIL
[AbortController interface object length]
expected: FAIL
[XPathExpression interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[XPathResult interface object length]
expected: FAIL
[Stringification of document.createExpression("//*")]
expected: FAIL
[XPathResult must be primary interface of document.evaluate("//*", document.body)]
expected: FAIL
[CharacterData interface: operation replaceWith((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: existence and properties of interface prototype object]
expected: FAIL
[XPathResult interface: attribute resultType]
expected: FAIL
[Document interface: xmlDoc must inherit property "createExpression(DOMString, optional XPathNSResolver?)" with the proper type]
expected: FAIL
[XPathResult interface: constant FIRST_ORDERED_NODE_TYPE on interface prototype object]
expected: FAIL
[DocumentType interface: operation replaceWith((Node or DOMString)...)]
expected: FAIL
[EventTarget interface: calling dispatchEvent(Event) on new AbortController().signal with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[AbortController interface: existence and properties of interface prototype object]
expected: FAIL
[Document interface: new Document() must inherit property "createNSResolver(Node)" with the proper type]
expected: FAIL
[XPathResult interface: constant ORDERED_NODE_ITERATOR_TYPE on interface prototype object]
expected: FAIL
[XPathResult interface: attribute stringValue]
expected: FAIL
[XPathResult interface: attribute booleanValue]
expected: FAIL
[XPathEvaluator interface: calling createExpression(DOMString, optional XPathNSResolver?) on new XPathEvaluator() with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "UNORDERED_NODE_SNAPSHOT_TYPE" with the proper type]
expected: FAIL
[DocumentFragment interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[XPathEvaluator interface: operation createNSResolver(Node)]
expected: FAIL
[Document interface: calling createNSResolver(Node) on xmlDoc with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "booleanValue" with the proper type]
expected: FAIL
[DocumentType interface: operation before((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: constant ORDERED_NODE_SNAPSHOT_TYPE on interface prototype object]
expected: FAIL
[AbortSignal interface: new AbortController().signal must inherit property "aborted" with the proper type]
expected: FAIL
[EventTarget interface: calling addEventListener(DOMString, EventListener?, optional (AddEventListenerOptions or boolean)) on new AbortController().signal with too few arguments must throw TypeError]
expected: FAIL
[Document interface: calling createExpression(DOMString, optional XPathNSResolver?) on xmlDoc with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: attribute snapshotLength]
expected: FAIL
[XPathEvaluator interface: new XPathEvaluator() must inherit property "createNSResolver(Node)" with the proper type]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "resultType" with the proper type]
expected: FAIL
[XPathEvaluator interface object length]
expected: FAIL
[AbortSignal interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[XPathEvaluator interface: new XPathEvaluator() must inherit property "evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?)" with the proper type]
expected: FAIL
[XPathEvaluator interface: calling evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?) on new XPathEvaluator() with too few arguments must throw TypeError]
expected: FAIL
[AbortSignal interface: new AbortController().signal must inherit property "onabort" with the proper type]
expected: FAIL
[Document interface: calling evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?) on xmlDoc with too few arguments must throw TypeError]
expected: FAIL
[XPathResult interface: constant UNORDERED_NODE_SNAPSHOT_TYPE on interface object]
expected: FAIL
[AbortController interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "stringValue" with the proper type]
expected: FAIL
[XPathResult interface: attribute invalidIteratorState]
expected: FAIL
[AbortSignal interface: attribute onabort]
expected: FAIL
[Document interface: operation evaluate(DOMString, Node, optional XPathNSResolver?, optional unsigned short, optional XPathResult?)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "singleNodeValue" with the proper type]
expected: FAIL
[Document interface: operation createExpression(DOMString, optional XPathNSResolver?)]
expected: FAIL
[AbortSignal interface object length]
expected: FAIL
[XPathEvaluator interface: calling createNSResolver(Node) on new XPathEvaluator() with too few arguments must throw TypeError]
expected: FAIL
[AbortSignal interface: existence and properties of interface prototype object]
expected: FAIL
[XPathResult interface: attribute numberValue]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "numberValue" with the proper type]
expected: FAIL
[XPathResult interface: constant NUMBER_TYPE on interface prototype object]
expected: FAIL
[XPathExpression interface object name]
expected: FAIL
[Event interface: new Event("foo") must inherit property "composed" with the proper type]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "BOOLEAN_TYPE" with the proper type]
expected: FAIL
[Document interface: new Document() must inherit property "createExpression(DOMString, optional XPathNSResolver?)" with the proper type]
expected: FAIL
[XPathResult interface: constant BOOLEAN_TYPE on interface prototype object]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "STRING_TYPE" with the proper type]
expected: FAIL
[Element interface: operation remove()]
expected: FAIL
[DocumentFragment interface: operation replaceChildren((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "NUMBER_TYPE" with the proper type]
expected: FAIL
[NodeFilter interface: existence and properties of interface object]
expected: FAIL
[XPathEvaluator interface object name]
expected: FAIL
[XPathExpression interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[Stringification of document.evaluate("//*", document.body)]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "ORDERED_NODE_SNAPSHOT_TYPE" with the proper type]
expected: FAIL
[Stringification of new AbortController().signal]
expected: FAIL
[XPathResult interface: constant ANY_UNORDERED_NODE_TYPE on interface prototype object]
expected: FAIL
[Document interface: calling createExpression(DOMString, optional XPathNSResolver?) on new Document() with too few arguments must throw TypeError]
expected: FAIL
[XPathEvaluator interface: new XPathEvaluator() must inherit property "createExpression(DOMString, optional XPathNSResolver?)" with the proper type]
expected: FAIL
[CharacterData interface: operation after((Node or DOMString)...)]
expected: FAIL
[XPathExpression interface object length]
expected: FAIL
[Stringification of new XPathEvaluator()]
expected: FAIL
[Element interface: operation replaceChildren((Node or DOMString)...)]
expected: FAIL
@ -445,66 +178,30 @@
[Document interface: operation replaceChildren((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: constant ANY_UNORDERED_NODE_TYPE on interface object]
expected: FAIL
[XPathExpression must be primary interface of document.createExpression("//*")]
expected: FAIL
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "FIRST_ORDERED_NODE_TYPE" with the proper type]
expected: FAIL
[Stringification of new AbortController()]
expected: FAIL
[XPathExpression interface: calling evaluate(Node, optional unsigned short, optional XPathResult?) on document.createExpression("//*") with too few arguments must throw TypeError]
expected: FAIL
[Document interface: operation append((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: operation iterateNext()]
expected: FAIL
[Event interface: document.createEvent("Event") must inherit property "composed" with the proper type]
expected: FAIL
[XPathResult interface: constant UNORDERED_NODE_ITERATOR_TYPE on interface object]
expected: FAIL
[DocumentType interface: operation remove()]
expected: FAIL
[XPathResult interface: constant ANY_TYPE on interface object]
expected: FAIL
[XPathResult interface: constant FIRST_ORDERED_NODE_TYPE on interface object]
expected: FAIL
[DocumentType interface: operation after((Node or DOMString)...)]
expected: FAIL
[XPathEvaluator must be primary interface of new XPathEvaluator()]
expected: FAIL
[XPathExpression interface: existence and properties of interface object]
expected: FAIL
[Element interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[DocumentFragment interface: operation append((Node or DOMString)...)]
expected: FAIL
[XPathResult interface: constant BOOLEAN_TYPE on interface object]
expected: FAIL
[Element interface: operation append((Node or DOMString)...)]
expected: FAIL
[XPathEvaluator interface: existence and properties of interface prototype object]
expected: FAIL
[Element interface: operation before((Node or DOMString)...)]
expected: FAIL
@ -649,9 +346,6 @@
[AbortSignal interface: new AbortController().signal must inherit property "throwIfAborted()" with the proper type]
expected: FAIL
[idl_test setup]
expected: FAIL
[AbortSignal interface: operation timeout(unsigned long long)]
expected: FAIL

View file

@ -0,0 +1,3 @@
[document.tentative.html]
[XPath parent of documentElement]
expected: FAIL

View file

@ -0,0 +1,21 @@
[fn-lang.html]
[lang("en"): <root><match lang="en"></match></root>]
expected: FAIL
[lang("en"): <root><match lang="EN"></match></root>]
expected: FAIL
[lang("en"): <root><match lang="en-us"></match></root>]
expected: FAIL
[lang("en"): <root><unmatch></unmatch></root>]
expected: FAIL
[lang("ja"): <root lang="ja"><match></match></root>]
expected: FAIL
[lang("ja"): <root lang="ja-jp"><unmatch lang="ja_JP"></unmatch></root>]
expected: FAIL
[lang("ko"): <root><unmatch lang="o"></unmatch></root>]
expected: FAIL

View file

@ -0,0 +1,6 @@
[lexical-structure.html]
[Literal: Only ' and " should be handled as literal quotes.]
expected: FAIL
[ExprWhitespace: Only #x20 #x9 #xD or #xA must be handled as a whitespace.]
expected: FAIL

View file

@ -0,0 +1,3 @@
[node-sets.html]
[| operator should evaluate both sides of expressions with the same context node]
expected: FAIL

View file

@ -0,0 +1,3 @@
[predicates.html]
[An expression in a predicate should not change the context node]
expected: FAIL

View file

@ -0,0 +1,15 @@
[resolver-callback-interface-cross-realm.tentative.html]
[XPathNSResolver is cross-realm plain object without 'lookupNamespaceURI' property]
expected: FAIL
[XPathNSResolver is cross-realm plain object with non-callable 'lookupNamespaceURI' property]
expected: FAIL
[XPathNSResolver is cross-realm non-callable revoked Proxy]
expected: FAIL
[XPathNSResolver is cross-realm callable revoked Proxy]
expected: FAIL
[XPathNSResolver is cross-realm plain object with revoked Proxy as 'lookupNamespaceURI' property]
expected: FAIL

View file

@ -0,0 +1,30 @@
[resolver-callback-interface.html]
[callable resolver]
expected: FAIL
[callable resolver: result is not cached]
expected: FAIL
[callable resolver: abrupt completion from Call]
expected: FAIL
[callable resolver: no 'lookupNamespaceURI' lookups]
expected: FAIL
[object resolver]
expected: FAIL
[object resolver: this value and `prefix` argument]
expected: FAIL
[object resolver: 'lookupNamespaceURI' is not cached]
expected: FAIL
[object resolver: abrupt completion from Get]
expected: FAIL
[object resolver: 'lookupNamespaceURI' is thruthy and not callable]
expected: FAIL
[object resolver: 'lookupNamespaceURI' is falsy and not callable]
expected: FAIL

View file

@ -0,0 +1,18 @@
[resolver-non-string-result.html]
[undefined]
expected: FAIL
[null]
expected: FAIL
[number]
expected: FAIL
[boolean]
expected: FAIL
[symbol]
expected: FAIL
[object coercion (abrupt completion)]
expected: FAIL

View file

@ -0,0 +1,39 @@
[text-html-attributes.html]
[Select html element based on attribute]
expected: FAIL
[Select html element based on attribute mixed case]
expected: FAIL
[Select both HTML and SVG elements based on attribute]
expected: FAIL
[Select HTML element with non-ascii attribute 1]
expected: FAIL
[Select HTML element with non-ascii attribute 2]
expected: FAIL
[Select HTML element with non-ascii attribute 3]
expected: FAIL
[Select SVG element based on mixed case attribute]
expected: FAIL
[Select both HTML and SVG elements based on mixed case attribute]
expected: FAIL
[Select SVG elements with refX attribute]
expected: FAIL
[Select SVG element with non-ascii attribute 1]
expected: FAIL
[Select SVG element with non-ascii attribute 2]
expected: FAIL
[xmlns attribute]
expected: FAIL
[svg element with XLink attribute]
expected: FAIL

View file

@ -0,0 +1,24 @@
[text-html-elements.html]
[HTML elements namespace prefix]
expected: FAIL
[HTML elements mixed use of prefix]
expected: FAIL
[SVG elements namespace prefix]
expected: FAIL
[HTML elements mixed case]
expected: FAIL
[SVG elements mixed case selector]
expected: FAIL
[Non-ascii HTML element]
expected: FAIL
[Non-ascii HTML element3]
expected: FAIL
[Throw with invalid prefix]
expected: FAIL

File diff suppressed because it is too large Load diff