diff options
author | Luke <luke.wilde@live.co.uk> | 2020-08-17 19:14:30 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-17 22:57:05 +0200 |
commit | 8b807e65d7fe423a35a7d506f89b0532f45aa032 (patch) | |
tree | 26a198bb82d6ccc131a7d8a42934d0c661003edf /Libraries/LibWeb/DOM | |
parent | 7b755e6a58b84ab81aad588b7eb17bc7f4be8c46 (diff) | |
download | serenity-8b807e65d7fe423a35a7d506f89b0532f45aa032.zip |
LibWeb: Add Comment and DocumentFragment bindings, move querySelector...
...{All} to ParentNode. Exposes createDocumentFragment and
createComment on Document. Stubs out the document.body setter.
Also adds ParentNode back :^).
Diffstat (limited to 'Libraries/LibWeb/DOM')
-rw-r--r-- | Libraries/LibWeb/DOM/Comment.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Comment.idl | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.cpp | 88 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.h | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.idl | 7 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/DocumentFragment.cpp | 40 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/DocumentFragment.h | 6 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/DocumentFragment.idl | 7 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Element.idl | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/ParentNode.cpp | 80 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/ParentNode.h | 5 |
11 files changed, 194 insertions, 52 deletions
diff --git a/Libraries/LibWeb/DOM/Comment.h b/Libraries/LibWeb/DOM/Comment.h index f0cdc7907a..855c710ded 100644 --- a/Libraries/LibWeb/DOM/Comment.h +++ b/Libraries/LibWeb/DOM/Comment.h @@ -33,6 +33,8 @@ namespace Web::DOM { class Comment final : public CharacterData { public: + using WrapperType = Bindings::CommentWrapper; + explicit Comment(Document&, const String&); virtual ~Comment() override; diff --git a/Libraries/LibWeb/DOM/Comment.idl b/Libraries/LibWeb/DOM/Comment.idl new file mode 100644 index 0000000000..a8c42f6a5e --- /dev/null +++ b/Libraries/LibWeb/DOM/Comment.idl @@ -0,0 +1,3 @@ +interface Comment : CharacterData { + +} diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index ebd6466456..61ba9f5b50 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -32,21 +32,20 @@ #include <LibJS/Interpreter.h> #include <LibJS/Parser.h> #include <LibJS/Runtime/Function.h> -#include <LibJS/Runtime/GlobalObject.h> #include <LibWeb/Bindings/DocumentWrapper.h> #include <LibWeb/Bindings/WindowObject.h> -#include <LibWeb/CSS/Parser/CSSParser.h> -#include <LibWeb/CSS/SelectorEngine.h> #include <LibWeb/CSS/StyleResolver.h> +#include <LibWeb/DOM/Comment.h> #include <LibWeb/DOM/Document.h> +#include <LibWeb/DOM/DocumentFragment.h> #include <LibWeb/DOM/DocumentType.h> #include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/ElementFactory.h> #include <LibWeb/DOM/Text.h> #include <LibWeb/DOM/Window.h> -#include <LibWeb/Dump.h> #include <LibWeb/HTML/AttributeNames.h> #include <LibWeb/HTML/HTMLBodyElement.h> +#include <LibWeb/HTML/HTMLFrameSetElement.h> #include <LibWeb/HTML/HTMLHeadElement.h> #include <LibWeb/HTML/HTMLHtmlElement.h> #include <LibWeb/HTML/HTMLScriptElement.h> @@ -149,7 +148,37 @@ const HTML::HTMLElement* Document::body() const auto* html = html_element(); if (!html) return nullptr; - return html->first_child_of_type<HTML::HTMLBodyElement>(); + auto* first_body = html->first_child_of_type<HTML::HTMLBodyElement>(); + if (first_body) + return first_body; + auto* first_frameset = html->first_child_of_type<HTML::HTMLFrameSetElement>(); + if (first_frameset) + return first_frameset; + return nullptr; +} + +void Document::set_body(HTML::HTMLElement& new_body) +{ + if (!is<HTML::HTMLBodyElement>(new_body) && !is<HTML::HTMLFrameSetElement>(new_body)) { + // FIXME: throw a "HierarchyRequestError" DOMException. + return; + } + + auto* existing_body = body(); + if (existing_body) { + TODO(); + return; + } + + auto* html = document_element(); + if (!html) { + // FIXME: throw a "HierarchyRequestError" DOMException. + return; + } + + // FIXME: Implement this once there's a non-const first_child_of_type: + // "Otherwise, the body element is null, but there's a document element. Append the new value to the document element." + TODO(); } String Document::title() const @@ -351,45 +380,6 @@ NonnullRefPtrVector<Element> Document::get_elements_by_tag_name(const FlyString& return elements; } -RefPtr<Element> Document::query_selector(const StringView& selector_text) -{ - auto selector = parse_selector(CSS::ParsingContext(*this), selector_text); - if (!selector.has_value()) - return {}; - - dump_selector(selector.value()); - - RefPtr<Element> result; - for_each_in_subtree_of_type<Element>([&](auto& element) { - if (SelectorEngine::matches(selector.value(), element)) { - result = element; - return IterationDecision::Break; - } - return IterationDecision::Continue; - }); - - return result; -} - -NonnullRefPtrVector<Element> Document::query_selector_all(const StringView& selector_text) -{ - auto selector = parse_selector(CSS::ParsingContext(*this), selector_text); - if (!selector.has_value()) - return {}; - - dump_selector(selector.value()); - - NonnullRefPtrVector<Element> elements; - for_each_in_subtree_of_type<Element>([&](auto& element) { - if (SelectorEngine::matches(selector.value(), element)) { - elements.append(element); - } - return IterationDecision::Continue; - }); - - return elements; -} - Color Document::link_color() const { if (m_link_color.has_value()) @@ -444,11 +434,21 @@ NonnullRefPtr<Element> Document::create_element(const String& tag_name) return DOM::create_element(*this, tag_name); } +NonnullRefPtr<DocumentFragment> Document::create_document_fragment() +{ + return adopt(*new DocumentFragment(*this)); +} + NonnullRefPtr<Text> Document::create_text_node(const String& data) { return adopt(*new Text(*this, data)); } +NonnullRefPtr<Comment> Document::create_comment(const String& data) +{ + return adopt(*new Comment(*this, data)); +} + void Document::set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement* script) { m_pending_parsing_blocking_script = script; diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index fc6910c490..03ed3108b0 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -89,6 +89,7 @@ public: const HTML::HTMLHtmlElement* html_element() const; const HTML::HTMLHeadElement* head() const; const HTML::HTMLElement* body() const; + void set_body(HTML::HTMLElement& new_body); String title() const; @@ -126,8 +127,6 @@ public: Vector<const Element*> get_elements_by_name(const String&) const; NonnullRefPtrVector<Element> get_elements_by_tag_name(const FlyString&) const; - RefPtr<Element> query_selector(const StringView&); - NonnullRefPtrVector<Element> query_selector_all(const StringView&); const String& source() const { return m_source; } void set_source(const String& source) { m_source = source; } @@ -137,7 +136,9 @@ public: JS::Value run_javascript(const StringView&); NonnullRefPtr<Element> create_element(const String& tag_name); + NonnullRefPtr<DocumentFragment> create_document_fragment(); NonnullRefPtr<Text> create_text_node(const String& data); + NonnullRefPtr<Comment> create_comment(const String& data); void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*); HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; } diff --git a/Libraries/LibWeb/DOM/Document.idl b/Libraries/LibWeb/DOM/Document.idl index f2cbf8eafa..48c2fd6765 100644 --- a/Libraries/LibWeb/DOM/Document.idl +++ b/Libraries/LibWeb/DOM/Document.idl @@ -4,12 +4,17 @@ interface Document : Node { Element? querySelector(DOMString selectors); ArrayFromVector getElementsByTagName(DOMString tagName); ArrayFromVector querySelectorAll(DOMString selectors); + Element createElement(DOMString tagName); + DocumentFragment createDocumentFragment(); + Text createTextNode(DOMString data); + Comment createComment(DOMString data); readonly attribute DOMString compatMode; readonly attribute DocumentType? doctype; readonly attribute Element? documentElement; - readonly attribute HTMLElement? body; + attribute HTMLElement? body; + readonly attribute HTMLHeadElement? head; } diff --git a/Libraries/LibWeb/DOM/DocumentFragment.cpp b/Libraries/LibWeb/DOM/DocumentFragment.cpp new file mode 100644 index 0000000000..92400feb70 --- /dev/null +++ b/Libraries/LibWeb/DOM/DocumentFragment.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Luke Wilde <luke.wilde@live.co.uk> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <LibWeb/DOM/DocumentFragment.h> + +namespace Web::DOM { + +DocumentFragment::DocumentFragment(Document& document) + : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE) +{ +} + +DocumentFragment::~DocumentFragment() +{ +} + +} diff --git a/Libraries/LibWeb/DOM/DocumentFragment.h b/Libraries/LibWeb/DOM/DocumentFragment.h index 9bc8f39d14..b969fbde4a 100644 --- a/Libraries/LibWeb/DOM/DocumentFragment.h +++ b/Libraries/LibWeb/DOM/DocumentFragment.h @@ -36,10 +36,8 @@ class DocumentFragment : public ParentNode , public NonElementParentNode<DocumentFragment> { public: - DocumentFragment(Document& document) - : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE) - { - } + DocumentFragment(Document& document); + virtual ~DocumentFragment() override; virtual FlyString node_name() const override { return "#document-fragment"; } }; diff --git a/Libraries/LibWeb/DOM/DocumentFragment.idl b/Libraries/LibWeb/DOM/DocumentFragment.idl new file mode 100644 index 0000000000..0b42cb9bfe --- /dev/null +++ b/Libraries/LibWeb/DOM/DocumentFragment.idl @@ -0,0 +1,7 @@ +interface DocumentFragment : Node { + + Element? getElementById(DOMString id); + Element? querySelector(DOMString selectors); + ArrayFromVector querySelectorAll(DOMString selectors); + +} diff --git a/Libraries/LibWeb/DOM/Element.idl b/Libraries/LibWeb/DOM/Element.idl index f586296c5d..082d0a951a 100644 --- a/Libraries/LibWeb/DOM/Element.idl +++ b/Libraries/LibWeb/DOM/Element.idl @@ -5,6 +5,9 @@ interface Element : Node { DOMString? getAttribute(DOMString qualifiedName); void setAttribute(DOMString qualifiedName, DOMString value); + Element? querySelector(DOMString selectors); + ArrayFromVector querySelectorAll(DOMString selectors); + attribute DOMString innerHTML; [Reflect] attribute DOMString id; [Reflect=class] attribute DOMString className; diff --git a/Libraries/LibWeb/DOM/ParentNode.cpp b/Libraries/LibWeb/DOM/ParentNode.cpp new file mode 100644 index 0000000000..31a84b9017 --- /dev/null +++ b/Libraries/LibWeb/DOM/ParentNode.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <LibWeb/CSS/Parser/CSSParser.h> +#include <LibWeb/CSS/SelectorEngine.h> +#include <LibWeb/DOM/ParentNode.h> +#include <LibWeb/Dump.h> + +namespace Web::DOM { + +void ParentNode::remove_all_children() +{ + while (RefPtr<Node> child = first_child()) { + remove_child(*child); + } +} + +RefPtr<Element> ParentNode::query_selector(const StringView& selector_text) +{ + auto selector = parse_selector(CSS::ParsingContext(*this), selector_text); + if (!selector.has_value()) + return {}; + + dump_selector(selector.value()); + + RefPtr<Element> result; + for_each_in_subtree_of_type<Element>([&](auto& element) { + if (SelectorEngine::matches(selector.value(), element)) { + result = element; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + + return result; +} + +NonnullRefPtrVector<Element> ParentNode::query_selector_all(const StringView& selector_text) +{ + auto selector = parse_selector(CSS::ParsingContext(*this), selector_text); + if (!selector.has_value()) + return {}; + + dump_selector(selector.value()); + + NonnullRefPtrVector<Element> elements; + for_each_in_subtree_of_type<Element>([&](auto& element) { + if (SelectorEngine::matches(selector.value(), element)) { + elements.append(element); + } + return IterationDecision::Continue; + }); + + return elements; +} + +} diff --git a/Libraries/LibWeb/DOM/ParentNode.h b/Libraries/LibWeb/DOM/ParentNode.h index 16b911fa80..23f0999795 100644 --- a/Libraries/LibWeb/DOM/ParentNode.h +++ b/Libraries/LibWeb/DOM/ParentNode.h @@ -35,8 +35,11 @@ public: template<typename F> void for_each_child(F) const; template<typename F> void for_each_child(F); + RefPtr<Element> query_selector(const StringView&); + NonnullRefPtrVector<Element> query_selector_all(const StringView&); + protected: - explicit ParentNode(Document& document, NodeType type) + ParentNode(Document& document, NodeType type) : Node(document, type) { } |