mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:47:34 +00:00
LibWeb: Propagate errors from CSS Parser construction
This requires Parser to be movable, so we remove the `default` destructors from Parser and TokenStream, and give them both move constructors. Since TokenStream only holds a reference to its tokens, (and it needs to, to avoid copying when given eg a function's contents,) we add a manual move constructor for Parser which creates a new TokenStream from the new Parser's tokens, and then manually copies the old TokenStream's state.
This commit is contained in:
parent
235018046e
commit
ca30914fe9
3 changed files with 47 additions and 22 deletions
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||||
* Copyright (c) 2020-2021, the SerenityOS developers.
|
* Copyright (c) 2020-2021, the SerenityOS developers.
|
||||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||||
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
||||||
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
|
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
|
||||||
*
|
*
|
||||||
|
@ -82,11 +82,29 @@ AK::URL ParsingContext::complete_url(StringView relative_url) const
|
||||||
return m_url.complete_url(relative_url);
|
return m_url.complete_url(relative_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser(ParsingContext const& context, StringView input, StringView encoding)
|
ErrorOr<Parser> Parser::create(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))
|
|
||||||
{
|
{
|
||||||
|
auto tokens = TRY(Tokenizer::tokenize(input, encoding));
|
||||||
|
return Parser { context, move(tokens) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser::Parser(ParsingContext const& context, Vector<Token> 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<Token>, 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
|
// 5.3.3. Parse a stylesheet
|
||||||
|
@ -7260,7 +7278,7 @@ RefPtr<CalculatedStyleValue> Parser::parse_calculated_value(Badge<StyleComputer>
|
||||||
if (tokens.is_empty())
|
if (tokens.is_empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
Parser parser(context, ""sv);
|
auto parser = Parser::create(context, ""sv).release_value_but_fixme_should_propagate_errors();
|
||||||
return parser.parse_calculated_value(tokens);
|
return parser.parse_calculated_value(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7269,7 +7287,7 @@ RefPtr<StyleValue> Parser::parse_css_value(Badge<StyleComputer>, ParsingContext
|
||||||
if (tokens.is_empty() || property_id == CSS::PropertyID::Invalid || property_id == CSS::PropertyID::Custom)
|
if (tokens.is_empty() || property_id == CSS::PropertyID::Invalid || property_id == CSS::PropertyID::Custom)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
Parser parser(context, ""sv);
|
auto parser = Parser::create(context, ""sv).release_value_but_fixme_should_propagate_errors();
|
||||||
TokenStream<ComponentValue> token_stream { tokens };
|
TokenStream<ComponentValue> token_stream { tokens };
|
||||||
auto result = parser.parse_css_value(property_id, token_stream);
|
auto result = parser.parse_css_value(property_id, token_stream);
|
||||||
if (result.is_error())
|
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();
|
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();
|
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);
|
return parser.parse_as_css_stylesheet(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7411,7 +7429,7 @@ CSS::ElementInlineCSSStyleDeclaration* parse_css_style_attribute(CSS::Parser::Pa
|
||||||
{
|
{
|
||||||
if (css.is_empty())
|
if (css.is_empty())
|
||||||
return CSS::ElementInlineCSSStyleDeclaration::create(element, {}, {}).release_value_but_fixme_should_propagate_errors();
|
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);
|
return parser.parse_as_style_attribute(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7419,31 +7437,31 @@ RefPtr<CSS::StyleValue> parse_css_value(CSS::Parser::ParsingContext const& conte
|
||||||
{
|
{
|
||||||
if (string.is_empty())
|
if (string.is_empty())
|
||||||
return {};
|
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);
|
return parser.parse_as_css_value(property_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSS::CSSRule* parse_css_rule(CSS::Parser::ParsingContext const& context, StringView css_text)
|
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();
|
return parser.parse_as_css_rule();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<CSS::SelectorList> parse_selector(CSS::Parser::ParsingContext const& context, StringView selector_text)
|
Optional<CSS::SelectorList> 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();
|
return parser.parse_as_selector();
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<CSS::MediaQuery> parse_media_query(CSS::Parser::ParsingContext const& context, StringView string)
|
RefPtr<CSS::MediaQuery> 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();
|
return parser.parse_as_media_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<NonnullRefPtr<CSS::MediaQuery>> parse_media_query_list(CSS::Parser::ParsingContext const& context, StringView string)
|
Vector<NonnullRefPtr<CSS::MediaQuery>> 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();
|
return parser.parse_as_media_query_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7451,7 +7469,7 @@ RefPtr<CSS::Supports> parse_css_supports(CSS::Parser::ParsingContext const& cont
|
||||||
{
|
{
|
||||||
if (string.is_empty())
|
if (string.is_empty())
|
||||||
return {};
|
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();
|
return parser.parse_as_supports();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7459,7 +7477,7 @@ Optional<CSS::StyleProperty> parse_css_supports_condition(CSS::Parser::ParsingCo
|
||||||
{
|
{
|
||||||
if (string.is_empty())
|
if (string.is_empty())
|
||||||
return {};
|
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();
|
return parser.parse_as_supports_condition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2021, the SerenityOS developers.
|
* Copyright (c) 2020-2021, the SerenityOS developers.
|
||||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -57,8 +57,9 @@ private:
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
Parser(ParsingContext const&, StringView input, StringView encoding = "utf-8"sv);
|
static ErrorOr<Parser> create(ParsingContext const&, StringView input, StringView encoding = "utf-8"sv);
|
||||||
~Parser() = default;
|
|
||||||
|
Parser(Parser&&);
|
||||||
|
|
||||||
CSSStyleSheet* parse_as_css_stylesheet(Optional<AK::URL> location);
|
CSSStyleSheet* parse_as_css_stylesheet(Optional<AK::URL> location);
|
||||||
ElementInlineCSSStyleDeclaration* parse_as_style_attribute(DOM::Element&);
|
ElementInlineCSSStyleDeclaration* parse_as_style_attribute(DOM::Element&);
|
||||||
|
@ -87,6 +88,8 @@ public:
|
||||||
static RefPtr<CalculatedStyleValue> parse_calculated_value(Badge<StyleComputer>, ParsingContext const&, Vector<ComponentValue> const&);
|
static RefPtr<CalculatedStyleValue> parse_calculated_value(Badge<StyleComputer>, ParsingContext const&, Vector<ComponentValue> const&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Parser(ParsingContext const&, Vector<Token>);
|
||||||
|
|
||||||
enum class ParseError {
|
enum class ParseError {
|
||||||
IncludesIgnoredVendorPrefix,
|
IncludesIgnoredVendorPrefix,
|
||||||
SyntaxError,
|
SyntaxError,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2021, the SerenityOS developers.
|
* Copyright (c) 2020-2021, the SerenityOS developers.
|
||||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -60,8 +60,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
TokenStream(TokenStream<T> const&) = delete;
|
TokenStream(TokenStream<T> const&) = delete;
|
||||||
|
TokenStream(TokenStream<T>&&) = default;
|
||||||
~TokenStream() = default;
|
|
||||||
|
|
||||||
bool has_next_token()
|
bool has_next_token()
|
||||||
{
|
{
|
||||||
|
@ -123,6 +122,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_state(Badge<Parser>, TokenStream<T> const& other)
|
||||||
|
{
|
||||||
|
m_iterator_offset = other.m_iterator_offset;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<T> const& m_tokens;
|
Vector<T> const& m_tokens;
|
||||||
int m_iterator_offset { -1 };
|
int m_iterator_offset { -1 };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue