summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt3
-rw-r--r--Userland/Libraries/LibWeb/DOM/Attribute.cpp24
-rw-r--r--Userland/Libraries/LibWeb/DOM/Attribute.h37
-rw-r--r--Userland/Libraries/LibWeb/DOM/Attribute.idl12
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.cpp12
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.h4
-rw-r--r--Userland/Libraries/LibWeb/Forward.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp38
-rw-r--r--Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h8
-rw-r--r--Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp4
10 files changed, 102 insertions, 42 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index 2f407f7703..f16da893c3 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -54,6 +54,8 @@ set(SOURCES
Cookie/ParsedCookie.cpp
DOM/AbortController.cpp
DOM/AbortSignal.cpp
+ DOM/Attribute.cpp
+ DOM/Attribute.idl
DOM/CharacterData.cpp
DOM/CharacterData.idl
DOM/Comment.cpp
@@ -366,6 +368,7 @@ libweb_js_wrapper(CSS/MediaQueryListEvent)
libweb_js_wrapper(CSS/Screen)
libweb_js_wrapper(CSS/StyleSheet)
libweb_js_wrapper(CSS/StyleSheetList)
+libweb_js_wrapper(DOM/Attribute)
libweb_js_wrapper(DOM/AbortController)
libweb_js_wrapper(DOM/AbortSignal)
libweb_js_wrapper(DOM/CharacterData)
diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.cpp b/Userland/Libraries/LibWeb/DOM/Attribute.cpp
new file mode 100644
index 0000000000..996a80a404
--- /dev/null
+++ b/Userland/Libraries/LibWeb/DOM/Attribute.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/DOM/Attribute.h>
+#include <LibWeb/DOM/Document.h>
+
+namespace Web::DOM {
+
+NonnullRefPtr<Attribute> Attribute::create(Document& document, FlyString local_name, String value)
+{
+ return adopt_ref(*new Attribute(document, move(local_name), move(value)));
+}
+
+Attribute::Attribute(Document& document, FlyString local_name, String value)
+ : Node(document, NodeType::ATTRIBUTE_NODE)
+ , m_qualified_name(move(local_name), {}, {})
+ , m_value(move(value))
+{
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.h b/Userland/Libraries/LibWeb/DOM/Attribute.h
index 5261a5bf7d..0a9dfd97b9 100644
--- a/Userland/Libraries/LibWeb/DOM/Attribute.h
+++ b/Userland/Libraries/LibWeb/DOM/Attribute.h
@@ -7,25 +7,42 @@
#pragma once
#include <AK/FlyString.h>
+#include <LibWeb/DOM/Node.h>
+#include <LibWeb/QualifiedName.h>
namespace Web::DOM {
-class Attribute {
+// https://dom.spec.whatwg.org/#attr
+class Attribute final : public Node {
public:
- Attribute(const FlyString& name, const String& value)
- : m_name(name)
- , m_value(value)
- {
- }
+ using WrapperType = Bindings::AttributeWrapper;
- const FlyString& name() const { return m_name; }
- const String& value() const { return m_value; }
+ static NonnullRefPtr<Attribute> create(Document&, FlyString local_name, String value);
- void set_value(const String& value) { m_value = value; }
+ virtual ~Attribute() override = default;
+
+ virtual FlyString node_name() const override { return name(); }
+
+ FlyString const& namespace_uri() const { return m_qualified_name.namespace_(); }
+ FlyString const& prefix() const { return m_qualified_name.prefix(); }
+ FlyString const& local_name() const { return m_qualified_name.local_name(); }
+ String const& name() const { return m_qualified_name.as_string(); }
+
+ String const& value() const { return m_value; }
+ void set_value(String value) { m_value = move(value); }
+
+ Element const* owner_element() const { return m_owner_element; }
+ void set_owner_element(Element const* owner_element) { m_owner_element = owner_element; }
+
+ // Always returns true: https://dom.spec.whatwg.org/#dom-attr-specified
+ constexpr bool specified() const { return true; }
private:
- FlyString m_name;
+ Attribute(Document&, FlyString local_name, String value);
+
+ QualifiedName m_qualified_name;
String m_value;
+ Element const* m_owner_element { nullptr };
};
}
diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.idl b/Userland/Libraries/LibWeb/DOM/Attribute.idl
new file mode 100644
index 0000000000..8b15866a3f
--- /dev/null
+++ b/Userland/Libraries/LibWeb/DOM/Attribute.idl
@@ -0,0 +1,12 @@
+[Exposed=Window]
+interface Attribute : Node {
+ readonly attribute DOMString? namespaceURI;
+ readonly attribute DOMString? prefix;
+ readonly attribute DOMString localName;
+ readonly attribute DOMString name;
+ [CEReactions] attribute DOMString value;
+
+ readonly attribute Element? ownerElement;
+
+ readonly attribute boolean specified;
+};
diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp
index bed9e07cfe..e6ea910150 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Element.cpp
@@ -49,8 +49,8 @@ Element::~Element()
Attribute* Element::find_attribute(const FlyString& name)
{
for (auto& attribute : m_attributes) {
- if (attribute.name() == name)
- return &attribute;
+ if (attribute->name() == name)
+ return attribute;
}
return nullptr;
}
@@ -58,8 +58,8 @@ Attribute* Element::find_attribute(const FlyString& name)
const Attribute* Element::find_attribute(const FlyString& name) const
{
for (auto& attribute : m_attributes) {
- if (attribute.name() == name)
- return &attribute;
+ if (attribute->name() == name)
+ return attribute;
}
return nullptr;
}
@@ -82,7 +82,7 @@ ExceptionOr<void> Element::set_attribute(const FlyString& name, const String& va
if (auto* attribute = find_attribute(name))
attribute->set_value(value);
else
- m_attributes.empend(name, value);
+ m_attributes.append(Attribute::create(document(), name, value));
parse_attribute(name, value);
return {};
@@ -92,7 +92,7 @@ void Element::remove_attribute(const FlyString& name)
{
CSS::StyleInvalidator style_invalidator(document());
- m_attributes.remove_first_matching([&](auto& attribute) { return attribute.name() == name; });
+ m_attributes.remove_first_matching([&](auto& attribute) { return attribute->name() == name; });
}
bool Element::has_class(const FlyString& class_name, CaseSensitivity case_sensitivity) const
diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h
index d23c640280..cc829ff53d 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.h
+++ b/Userland/Libraries/LibWeb/DOM/Element.h
@@ -67,7 +67,7 @@ public:
void for_each_attribute(Callback callback) const
{
for (auto& attribute : m_attributes)
- callback(attribute.name(), attribute.value());
+ callback(attribute->name(), attribute->value());
}
bool has_class(const FlyString&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
@@ -132,7 +132,7 @@ private:
QualifiedName m_qualified_name;
String m_html_uppercased_qualified_name;
- Vector<Attribute> m_attributes;
+ Vector<NonnullRefPtr<Attribute>> m_attributes;
RefPtr<CSS::CSSStyleDeclaration> m_inline_style;
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index ab862c7c11..2f3dd779dd 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -71,6 +71,7 @@ class UnsetStyleValue;
namespace Web::DOM {
class AbortController;
class AbortSignal;
+class Attribute;
class CharacterData;
class Comment;
class CustomEvent;
@@ -290,6 +291,7 @@ class URLSearchParamsIterator;
namespace Web::Bindings {
class AbortControllerWrapper;
class AbortSignalWrapper;
+class AttributeWrapper;
class CanvasRenderingContext2DWrapper;
class CharacterDataWrapper;
class CloseEventWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp
index 460e0a3872..f0c5c524b1 100644
--- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.cpp
@@ -9,6 +9,8 @@
#include <AK/StringView.h>
#include <AK/Utf8View.h>
#include <LibTextCodec/Decoder.h>
+#include <LibWeb/DOM/Attribute.h>
+#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
#include <ctype.h>
@@ -94,7 +96,7 @@ Optional<String> extract_character_encoding_from_meta_element(String const& stri
return TextCodec::get_standardized_encoding(encoding);
}
-Optional<DOM::Attribute> prescan_get_attribute(const ByteBuffer& input, size_t& position)
+RefPtr<DOM::Attribute> prescan_get_attribute(DOM::Document& document, const ByteBuffer& input, size_t& position)
{
if (!prescan_skip_whitespace_and_slashes(input, position))
return {};
@@ -109,7 +111,7 @@ Optional<DOM::Attribute> prescan_get_attribute(const ByteBuffer& input, size_t&
} else if (input[position] == '\t' || input[position] == '\n' || input[position] == '\f' || input[position] == '\r' || input[position] == ' ')
goto spaces;
else if (input[position] == '/' || input[position] == '>')
- return DOM::Attribute(attribute_name.to_string(), "");
+ return DOM::Attribute::create(document, attribute_name.to_string(), "");
else
attribute_name.append_as_lowercase(input[position]);
++position;
@@ -121,7 +123,7 @@ spaces:
if (!prescan_skip_whitespace_and_slashes(input, position))
return {};
if (input[position] != '=')
- return DOM::Attribute(attribute_name.to_string(), "");
+ return DOM::Attribute::create(document, attribute_name.to_string(), "");
++position;
value:
@@ -134,13 +136,13 @@ value:
++position;
for (; !prescan_should_abort(input, position); ++position) {
if (input[position] == quote_character)
- return DOM::Attribute(attribute_name.to_string(), attribute_value.to_string());
+ return DOM::Attribute::create(document, attribute_name.to_string(), attribute_value.to_string());
else
attribute_value.append_as_lowercase(input[position]);
}
return {};
} else if (input[position] == '>')
- return DOM::Attribute(attribute_name.to_string(), "");
+ return DOM::Attribute::create(document, attribute_name.to_string(), "");
else
attribute_value.append_as_lowercase(input[position]);
@@ -150,7 +152,7 @@ value:
for (; !prescan_should_abort(input, position); ++position) {
if (input[position] == '\t' || input[position] == '\n' || input[position] == '\f' || input[position] == '\r' || input[position] == ' ' || input[position] == '>')
- return DOM::Attribute(attribute_name.to_string(), attribute_value.to_string());
+ return DOM::Attribute::create(document, attribute_name.to_string(), attribute_value.to_string());
else
attribute_value.append_as_lowercase(input[position]);
}
@@ -158,7 +160,7 @@ value:
}
// https://html.spec.whatwg.org/multipage/parsing.html#prescan-a-byte-stream-to-determine-its-encoding
-Optional<String> run_prescan_byte_stream_algorithm(const ByteBuffer& input)
+Optional<String> run_prescan_byte_stream_algorithm(DOM::Document& document, const ByteBuffer& input)
{
// https://html.spec.whatwg.org/multipage/parsing.html#prescan-a-byte-stream-to-determine-its-encoding
@@ -194,24 +196,24 @@ Optional<String> run_prescan_byte_stream_algorithm(const ByteBuffer& input)
Optional<String> charset {};
while (true) {
- auto attribute = prescan_get_attribute(input, position);
- if (!attribute.has_value())
+ auto attribute = prescan_get_attribute(document, input, position);
+ if (!attribute)
break;
- if (attribute_list.contains_slow(attribute.value().name()))
+ if (attribute_list.contains_slow(attribute->name()))
continue;
- auto& attribute_name = attribute.value().name();
- attribute_list.append(attribute.value().name());
+ auto& attribute_name = attribute->name();
+ attribute_list.append(attribute->name());
if (attribute_name == "http-equiv") {
- got_pragma = attribute.value().value() == "content-type";
+ got_pragma = attribute->value() == "content-type";
} else if (attribute_name == "content") {
- auto encoding = extract_character_encoding_from_meta_element(attribute.value().value());
+ auto encoding = extract_character_encoding_from_meta_element(attribute->value());
if (encoding.has_value() && !charset.has_value()) {
charset = encoding.value();
need_pragma = true;
}
} else if (attribute_name == "charset") {
- auto maybe_charset = TextCodec::get_standardized_encoding(attribute.value().value());
+ auto maybe_charset = TextCodec::get_standardized_encoding(attribute->value());
if (maybe_charset.has_value()) {
charset = Optional<String> { maybe_charset };
need_pragma = { false };
@@ -231,7 +233,7 @@ Optional<String> run_prescan_byte_stream_algorithm(const ByteBuffer& input)
&& ((input[position + 1] == '/' && isalpha(input[position + 2])) || isalpha(input[position + 1]))) {
position += 2;
prescan_skip_whitespace_and_slashes(input, position);
- while (prescan_get_attribute(input, position).has_value()) { };
+ while (prescan_get_attribute(document, input, position)) { };
} else if (!prescan_should_abort(input, position + 1) && input[position] == '<' && (input[position + 1] == '!' || input[position + 1] == '/' || input[position + 1] == '?')) {
position += 2;
while (input[position] != '>') {
@@ -247,7 +249,7 @@ Optional<String> run_prescan_byte_stream_algorithm(const ByteBuffer& input)
}
// https://html.spec.whatwg.org/multipage/parsing.html#determining-the-character-encoding
-String run_encoding_sniffing_algorithm(const ByteBuffer& input)
+String run_encoding_sniffing_algorithm(DOM::Document& document, const ByteBuffer& input)
{
if (input.size() >= 2) {
if (input[0] == 0xFE && input[1] == 0xFF) {
@@ -265,7 +267,7 @@ String run_encoding_sniffing_algorithm(const ByteBuffer& input)
// at any later step in this algorithm.
// FIXME: If the transport layer specifies a character encoding, and it is supported.
- auto optional_encoding = run_prescan_byte_stream_algorithm(input);
+ auto optional_encoding = run_prescan_byte_stream_algorithm(document, input);
if (optional_encoding.has_value()) {
return optional_encoding.value();
}
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h
index 4d9a1e9ab2..52784e8d7c 100644
--- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h
+++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLEncodingDetection.h
@@ -8,7 +8,7 @@
#include <AK/Optional.h>
#include <AK/String.h>
-#include <LibWeb/DOM/Attribute.h>
+#include <LibWeb/Forward.h>
namespace Web::HTML {
@@ -16,8 +16,8 @@ bool prescan_should_abort(const ByteBuffer& input, const size_t& position);
bool prescan_is_whitespace_or_slash(const u8& byte);
bool prescan_skip_whitespace_and_slashes(const ByteBuffer& input, size_t& position);
Optional<String> extract_character_encoding_from_meta_element(String const&);
-Optional<DOM::Attribute> prescan_get_attribute(const ByteBuffer& input, size_t& position);
-Optional<String> run_prescan_byte_stream_algorithm(const ByteBuffer& input);
-String run_encoding_sniffing_algorithm(const ByteBuffer& input);
+RefPtr<DOM::Attribute> prescan_get_attribute(DOM::Document&, const ByteBuffer& input, size_t& position);
+Optional<String> run_prescan_byte_stream_algorithm(DOM::Document&, const ByteBuffer& input);
+String run_encoding_sniffing_algorithm(DOM::Document&, const ByteBuffer& input);
}
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
index d9fc29f64b..1a7ada5a10 100644
--- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
@@ -2810,7 +2810,7 @@ void HTMLParser::handle_in_frameset(HTMLToken& token)
}
if (token.is_end_of_file()) {
- //FIXME: If the current node is not the root html element, then this is a parse error.
+ // FIXME: If the current node is not the root html element, then this is a parse error.
stop_parsing();
return;
@@ -3162,7 +3162,7 @@ NonnullOwnPtr<HTMLParser> HTMLParser::create_with_uncertain_encoding(DOM::Docume
{
if (document.has_encoding())
return make<HTMLParser>(document, input, document.encoding().value());
- auto encoding = run_encoding_sniffing_algorithm(input);
+ auto encoding = run_encoding_sniffing_algorithm(document, input);
dbgln("The encoding sniffing algorithm returned encoding '{}'", encoding);
return make<HTMLParser>(document, input, encoding);
}