diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index f537edca45..92d0cada9d 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2022, Andreas Kling * Copyright (c) 2020-2021, the SerenityOS developers. - * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2022, MacDue * @@ -82,11 +82,29 @@ AK::URL ParsingContext::complete_url(StringView relative_url) const return m_url.complete_url(relative_url); } -Parser::Parser(ParsingContext const& context, StringView input, StringView encoding) - : m_context(context) - , m_tokens(Tokenizer::tokenize(input, encoding).release_value_but_fixme_should_propagate_errors()) - , m_token_stream(TokenStream(m_tokens)) +ErrorOr Parser::create(ParsingContext const& context, StringView input, StringView encoding) { + auto tokens = TRY(Tokenizer::tokenize(input, encoding)); + return Parser { context, move(tokens) }; +} + +Parser::Parser(ParsingContext const& context, Vector tokens) + : m_context(context) + , m_tokens(move(tokens)) + , m_token_stream(m_tokens) +{ +} + +Parser::Parser(Parser&& other) + : m_context(other.m_context) + , m_tokens(move(other.m_tokens)) + , m_token_stream(m_tokens) +{ + // Moving the TokenStream directly from `other` would break it, because TokenStream holds + // a reference to the Vector, so it would be pointing at the old Parser's tokens. + // So instead, we create a new TokenStream from this Parser's tokens, and then tell it to + // copy the other TokenStream's state. This is quite hacky. + m_token_stream.copy_state({}, other.m_token_stream); } // 5.3.3. Parse a stylesheet @@ -7260,7 +7278,7 @@ RefPtr Parser::parse_calculated_value(Badge if (tokens.is_empty()) return {}; - Parser parser(context, ""sv); + auto parser = Parser::create(context, ""sv).release_value_but_fixme_should_propagate_errors(); return parser.parse_calculated_value(tokens); } @@ -7269,7 +7287,7 @@ RefPtr Parser::parse_css_value(Badge, ParsingContext if (tokens.is_empty() || property_id == CSS::PropertyID::Invalid || property_id == CSS::PropertyID::Custom) return {}; - Parser parser(context, ""sv); + auto parser = Parser::create(context, ""sv).release_value_but_fixme_should_propagate_errors(); TokenStream token_stream { tokens }; auto result = parser.parse_css_value(property_id, token_stream); if (result.is_error()) @@ -7403,7 +7421,7 @@ CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const& cont auto media_list = CSS::MediaList::create(context.realm(), {}).release_value_but_fixme_should_propagate_errors(); return CSS::CSSStyleSheet::create(context.realm(), rule_list, media_list, location).release_value_but_fixme_should_propagate_errors(); } - CSS::Parser::Parser parser(context, css); + auto parser = CSS::Parser::Parser::create(context, css).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_css_stylesheet(location); } @@ -7411,7 +7429,7 @@ CSS::ElementInlineCSSStyleDeclaration* parse_css_style_attribute(CSS::Parser::Pa { if (css.is_empty()) return CSS::ElementInlineCSSStyleDeclaration::create(element, {}, {}).release_value_but_fixme_should_propagate_errors(); - CSS::Parser::Parser parser(context, css); + auto parser = CSS::Parser::Parser::create(context, css).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_style_attribute(element); } @@ -7419,31 +7437,31 @@ RefPtr parse_css_value(CSS::Parser::ParsingContext const& conte { if (string.is_empty()) return {}; - CSS::Parser::Parser parser(context, string); + auto parser = CSS::Parser::Parser::create(context, string).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_css_value(property_id); } CSS::CSSRule* parse_css_rule(CSS::Parser::ParsingContext const& context, StringView css_text) { - CSS::Parser::Parser parser(context, css_text); + auto parser = CSS::Parser::Parser::create(context, css_text).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_css_rule(); } Optional parse_selector(CSS::Parser::ParsingContext const& context, StringView selector_text) { - CSS::Parser::Parser parser(context, selector_text); + auto parser = CSS::Parser::Parser::create(context, selector_text).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_selector(); } RefPtr parse_media_query(CSS::Parser::ParsingContext const& context, StringView string) { - CSS::Parser::Parser parser(context, string); + auto parser = CSS::Parser::Parser::create(context, string).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_media_query(); } Vector> parse_media_query_list(CSS::Parser::ParsingContext const& context, StringView string) { - CSS::Parser::Parser parser(context, string); + auto parser = CSS::Parser::Parser::create(context, string).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_media_query_list(); } @@ -7451,7 +7469,7 @@ RefPtr parse_css_supports(CSS::Parser::ParsingContext const& cont { if (string.is_empty()) return {}; - CSS::Parser::Parser parser(context, string); + auto parser = CSS::Parser::Parser::create(context, string).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_supports(); } @@ -7459,7 +7477,7 @@ Optional parse_css_supports_condition(CSS::Parser::ParsingCo { if (string.is_empty()) return {}; - CSS::Parser::Parser parser(context, string); + auto parser = CSS::Parser::Parser::create(context, string).release_value_but_fixme_should_propagate_errors(); return parser.parse_as_supports_condition(); } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index fe0d2ec1b8..59e32c553b 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021, the SerenityOS developers. - * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -57,8 +57,9 @@ private: class Parser { public: - Parser(ParsingContext const&, StringView input, StringView encoding = "utf-8"sv); - ~Parser() = default; + static ErrorOr create(ParsingContext const&, StringView input, StringView encoding = "utf-8"sv); + + Parser(Parser&&); CSSStyleSheet* parse_as_css_stylesheet(Optional location); ElementInlineCSSStyleDeclaration* parse_as_style_attribute(DOM::Element&); @@ -87,6 +88,8 @@ public: static RefPtr parse_calculated_value(Badge, ParsingContext const&, Vector const&); private: + Parser(ParsingContext const&, Vector); + enum class ParseError { IncludesIgnoredVendorPrefix, SyntaxError, diff --git a/Userland/Libraries/LibWeb/CSS/Parser/TokenStream.h b/Userland/Libraries/LibWeb/CSS/Parser/TokenStream.h index 7f99c4ee0f..7cbc4f2e84 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/TokenStream.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/TokenStream.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021, the SerenityOS developers. - * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2021-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -60,8 +60,7 @@ public: { } TokenStream(TokenStream const&) = delete; - - ~TokenStream() = default; + TokenStream(TokenStream&&) = default; bool has_next_token() { @@ -123,6 +122,11 @@ public: } } + void copy_state(Badge, TokenStream const& other) + { + m_iterator_offset = other.m_iterator_offset; + } + private: Vector const& m_tokens; int m_iterator_offset { -1 };