LibWeb: Add implementation of Node.compareDocumentPosition()
While looking into getting Duck Duck Go loading further in the Browser, I noticed that it was complaining about the missing method Node.compareDocumentPosition. This change implements as much of the DOM spec as possible with the current implementation of the DOM to date. The implementation is validated by new tests in the Node.js.
This commit is contained in:
parent
0f8932d7ab
commit
988c23fff0
Notes:
sideshowbarker
2024-07-18 20:33:23 +09:00
Author: https://github.com/bgianfo Commit: https://github.com/SerenityOS/serenity/commit/988c23fff05 Pull-request: https://github.com/SerenityOS/serenity/pull/6230
4 changed files with 69 additions and 0 deletions
|
@ -454,6 +454,43 @@ void Node::remove_all_children(bool suppress_observers)
|
|||
child->remove(suppress_observers);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-node-comparedocumentposition
|
||||
u16 Node::compare_document_position(RefPtr<Node> other)
|
||||
{
|
||||
enum Position : u16 {
|
||||
DOCUMENT_POSITION_EQUAL = 0,
|
||||
DOCUMENT_POSITION_DISCONNECTED = 1,
|
||||
DOCUMENT_POSITION_PRECEDING = 2,
|
||||
DOCUMENT_POSITION_FOLLOWING = 4,
|
||||
DOCUMENT_POSITION_CONTAINS = 8,
|
||||
DOCUMENT_POSITION_CONTAINED_BY = 16,
|
||||
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32,
|
||||
};
|
||||
|
||||
if (this == other)
|
||||
return DOCUMENT_POSITION_EQUAL;
|
||||
|
||||
Node* node1 = other.ptr();
|
||||
Node* node2 = this;
|
||||
|
||||
// FIXME: Once LibWeb supports attribute nodes fix to follow the specification.
|
||||
VERIFY(node1->type() != NodeType::ATTRIBUTE_NODE && node2->type() != NodeType::ATTRIBUTE_NODE);
|
||||
|
||||
if ((node1 == nullptr || node2 == nullptr) || (node1->root() != node2->root()))
|
||||
return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | (node1 > node2 ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING);
|
||||
|
||||
if (node1->is_ancestor_of(*node2))
|
||||
return DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING;
|
||||
|
||||
if (node2->is_ancestor_of(*node1))
|
||||
return DOCUMENT_POSITION_CONTAINED_BY | DOCUMENT_POSITION_FOLLOWING;
|
||||
|
||||
if (node1->is_before(*node2))
|
||||
return DOCUMENT_POSITION_PRECEDING;
|
||||
else
|
||||
return DOCUMENT_POSITION_FOLLOWING;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-tree-host-including-inclusive-ancestor
|
||||
bool Node::is_host_including_inclusive_ancestor_of(const Node& other) const
|
||||
{
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
void insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool suppress_observers = false);
|
||||
void remove(bool suppress_observers = false);
|
||||
void remove_all_children(bool suppress_observers = false);
|
||||
u16 compare_document_position(RefPtr<Node> other);
|
||||
|
||||
// NOTE: This is intended for the JS bindings.
|
||||
bool has_child_nodes() const { return has_children(); }
|
||||
|
|
|
@ -32,4 +32,12 @@ interface Node : EventTarget {
|
|||
const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
|
||||
const unsigned short NOTATION_NODE = 12;
|
||||
|
||||
unsigned short compareDocumentPosition(Node? otherNode);
|
||||
// Node.compareDocumentPosition() constants
|
||||
const unsigned short DOCUMENT_POSITION_DISCONNECTED = 1;
|
||||
const unsigned short DOCUMENT_POSITION_PRECEDING = 2;
|
||||
const unsigned short DOCUMENT_POSITION_FOLLOWING = 4;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINS = 8;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 16;
|
||||
const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32;
|
||||
};
|
||||
|
|
|
@ -36,4 +36,27 @@ afterInitialPageLoad(() => {
|
|||
document.body.removeChild(element);
|
||||
expect(element.isConnected).toBeFalse();
|
||||
});
|
||||
|
||||
test("Node.compareDocumentPosition()", () => {
|
||||
const head = document.head;
|
||||
const body = document.body;
|
||||
|
||||
expect(head.compareDocumentPosition(head)).toBe(0);
|
||||
|
||||
// FIXME: Can be uncommented once the IDL parser correctly implements nullable paramaters.
|
||||
// expect(head.compareDocumentPosition(null) & Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC).
|
||||
// toBe(Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
|
||||
|
||||
expect(head.compareDocumentPosition(body)).toBe(Node.DOCUMENT_POSITION_FOLLOWING);
|
||||
expect(body.compareDocumentPosition(head)).toBe(Node.DOCUMENT_POSITION_PRECEDING);
|
||||
|
||||
const source = document.getElementById("source");
|
||||
expect(source.compareDocumentPosition(body)).toBe(
|
||||
Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING
|
||||
);
|
||||
expect(body.compareDocumentPosition(source)).toBe(
|
||||
Node.DOCUMENT_POSITION_CONTAINED_BY | Node.DOCUMENT_POSITION_FOLLOWING
|
||||
);
|
||||
expect(source.compareDocumentPosition(head)).toBe(Node.DOCUMENT_POSITION_PRECEDING);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue