Commit dee24f8f authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Chromium LUCI CQ

[@container] Add basic parsing based on media queries

The rule can be parsed, but can otherwise not be used for anything yet.

As temporary behavior, @container rules accepts anything accepted by
@media. Eventually we need to restrict what is accepted, and/or
implement a separate parser.

Bug: 1146095
Change-Id: I018008d291f2e353b20ad6624b1310f9da552e75
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2575028Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835147}
parent c641fdaa
...@@ -547,6 +547,8 @@ generated_interface_sources_in_core = [ ...@@ -547,6 +547,8 @@ generated_interface_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_animation.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_animation.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_condition_rule.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_condition_rule.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_condition_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_condition_rule.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_container_rule.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_container_rule.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_counter_style_rule.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_counter_style_rule.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_counter_style_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_counter_style_rule.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_font_face_rule.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_font_face_rule.cc",
......
...@@ -39,6 +39,7 @@ static_idl_files_in_core = get_path_info( ...@@ -39,6 +39,7 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/clipboard/data_transfer_item_list.idl", "//third_party/blink/renderer/core/clipboard/data_transfer_item_list.idl",
"//third_party/blink/renderer/core/css/css.idl", "//third_party/blink/renderer/core/css/css.idl",
"//third_party/blink/renderer/core/css/css_condition_rule.idl", "//third_party/blink/renderer/core/css/css_condition_rule.idl",
"//third_party/blink/renderer/core/css/css_container_rule.idl",
"//third_party/blink/renderer/core/css/css_counter_style_rule.idl", "//third_party/blink/renderer/core/css/css_counter_style_rule.idl",
"//third_party/blink/renderer/core/css/css_font_face_rule.idl", "//third_party/blink/renderer/core/css/css_font_face_rule.idl",
"//third_party/blink/renderer/core/css/css_grouping_rule.idl", "//third_party/blink/renderer/core/css/css_grouping_rule.idl",
......
...@@ -56,6 +56,7 @@ core_interface_idl_files_core_only = ...@@ -56,6 +56,7 @@ core_interface_idl_files_core_only =
"clipboard/data_transfer.idl", "clipboard/data_transfer.idl",
"clipboard/data_transfer_item_list.idl", "clipboard/data_transfer_item_list.idl",
"css/css_condition_rule.idl", "css/css_condition_rule.idl",
"css/css_container_rule.idl",
"css/css_counter_style_rule.idl", "css/css_counter_style_rule.idl",
"css/css_font_face_rule.idl", "css/css_font_face_rule.idl",
"css/css_grouping_rule.idl", "css/css_grouping_rule.idl",
......
...@@ -19,6 +19,8 @@ blink_core_sources_css = [ ...@@ -19,6 +19,8 @@ blink_core_sources_css = [
"counter_style.h", "counter_style.h",
"counter_style_map.cc", "counter_style_map.cc",
"counter_style_map.h", "counter_style_map.h",
"container_query.cc",
"container_query.h",
"css_axis_value.cc", "css_axis_value.cc",
"css_axis_value.h", "css_axis_value.h",
"css_basic_shape_values.cc", "css_basic_shape_values.cc",
...@@ -33,6 +35,8 @@ blink_core_sources_css = [ ...@@ -33,6 +35,8 @@ blink_core_sources_css = [
"css_computed_style_declaration.h", "css_computed_style_declaration.h",
"css_condition_rule.cc", "css_condition_rule.cc",
"css_condition_rule.h", "css_condition_rule.h",
"css_container_rule.cc",
"css_container_rule.h",
"css_content_distribution_value.cc", "css_content_distribution_value.cc",
"css_content_distribution_value.h", "css_content_distribution_value.h",
"css_counter_style_rule.cc", "css_counter_style_rule.cc",
...@@ -610,6 +614,7 @@ blink_core_tests_css = [ ...@@ -610,6 +614,7 @@ blink_core_tests_css = [
"active_style_sheets_test.cc", "active_style_sheets_test.cc",
"affected_by_pseudo_test.cc", "affected_by_pseudo_test.cc",
"computed_style_css_value_mapping_test.cc", "computed_style_css_value_mapping_test.cc",
"container_query_test.cc",
"css_computed_style_declaration_test.cc", "css_computed_style_declaration_test.cc",
"css_element_offset_value_test.cc", "css_element_offset_value_test.cc",
"css_font_face_source_test.cc", "css_font_face_source_test.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/container_query.h"
namespace blink {
ContainerQuery::ContainerQuery(scoped_refptr<MediaQuerySet> media_queries)
: media_queries_(media_queries) {}
ContainerQuery::ContainerQuery(const ContainerQuery& other)
: media_queries_(other.media_queries_->Copy()) {}
String ContainerQuery::ToString() const {
return media_queries_->MediaText();
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_QUERY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_QUERY_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/media_list.h"
namespace blink {
class CORE_EXPORT ContainerQuery final
: public GarbageCollected<ContainerQuery> {
public:
explicit ContainerQuery(scoped_refptr<MediaQuerySet>);
ContainerQuery(const ContainerQuery&);
String ToString() const;
void Trace(Visitor*) const {}
private:
friend class ContainerQueryTest;
// TODO(crbug.com/1145970): Refactor to avoid internal MediaQuerySet.
scoped_refptr<MediaQuerySet> media_queries_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_QUERY_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/container_query.h"
#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
class ContainerQueryTest : public PageTestBase,
private ScopedCSSContainerQueriesForTest {
public:
ContainerQueryTest() : ScopedCSSContainerQueriesForTest(true) {}
StyleRuleContainer* ParseAtContainer(String rule_string) {
return DynamicTo<StyleRuleContainer>(
css_test_helpers::ParseRule(GetDocument(), rule_string));
}
String SerializeCondition(StyleRuleContainer* container) {
if (!container)
return "";
return container->GetContainerQuery().ToString();
}
// TODO(crbug.com/1145970): Remove this when ContainerQuery no longer
// relies on MediaQuerySet.
MediaQuerySet& GetMediaQuerySet(ContainerQuery& container_query) {
return *container_query.media_queries_;
}
};
TEST_F(ContainerQueryTest, PreludeParsing) {
// Valid:
EXPECT_EQ(
"(min-width: 300px)",
SerializeCondition(ParseAtContainer("@container (min-width: 300px) {}")));
EXPECT_EQ(
"(max-width: 500px)",
SerializeCondition(ParseAtContainer("@container (max-width: 500px) {}")));
// TODO(crbug.com/1145970): The MediaQuery parser emits a "not all"
// MediaQuery for parse failures. When ContainerQuery has its own parser,
// it should probably return nullptr instead.
// Invalid:
EXPECT_EQ("not all",
SerializeCondition(ParseAtContainer("@container 100px {}")));
EXPECT_EQ("not all",
SerializeCondition(ParseAtContainer("@container calc(1) {}")));
}
TEST_F(ContainerQueryTest, RuleParsing) {
StyleRuleContainer* container = ParseAtContainer(R"CSS(
@container (min-width: 100px) {
div { width: 100px; }
span { height: 100px; }
}
)CSS");
ASSERT_TRUE(container);
CSSStyleSheet* sheet = css_test_helpers::CreateStyleSheet(GetDocument());
auto* rule =
DynamicTo<CSSContainerRule>(container->CreateCSSOMWrapper(sheet));
ASSERT_TRUE(rule);
ASSERT_EQ(2u, rule->length());
auto* div_rule = rule->Item(0);
ASSERT_TRUE(div_rule);
EXPECT_EQ("div { width: 100px; }", div_rule->cssText());
auto* span_rule = rule->Item(1);
ASSERT_TRUE(span_rule);
EXPECT_EQ("span { height: 100px; }", span_rule->cssText());
}
TEST_F(ContainerQueryTest, RuleCopy) {
StyleRuleContainer* container = ParseAtContainer(R"CSS(
@container (min-width: 100px) {
div { width: 100px; }
}
)CSS");
ASSERT_TRUE(container);
// Copy via StyleRuleBase to test switch dispatch.
auto* copy_base = static_cast<StyleRuleBase*>(container)->Copy();
auto* copy = DynamicTo<StyleRuleContainer>(copy_base);
ASSERT_TRUE(copy);
// The StyleRuleContainer object should be copied.
EXPECT_NE(container, copy);
// The rules should be copied.
auto rules = container->ChildRules();
auto rules_copy = copy->ChildRules();
ASSERT_EQ(1u, rules.size());
ASSERT_EQ(1u, rules_copy.size());
EXPECT_NE(rules[0], rules_copy[0]);
// The ContainerQuery should be copied.
EXPECT_NE(&container->GetContainerQuery(), &copy->GetContainerQuery());
// The inner MediaQuerySet should be copied.
EXPECT_NE(&GetMediaQuerySet(container->GetContainerQuery()),
&GetMediaQuerySet(copy->GetContainerQuery()));
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
CSSContainerRule::CSSContainerRule(StyleRuleContainer* container_rule,
CSSStyleSheet* parent)
: CSSConditionRule(container_rule, parent) {}
CSSContainerRule::~CSSContainerRule() = default;
String CSSContainerRule::cssText() const {
// TODO(crbug.com/1145970): Spec and implement serialization.
NOTIMPLEMENTED();
return "";
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_CONTAINER_RULE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_CONTAINER_RULE_H_
#include "third_party/blink/renderer/core/css/css_condition_rule.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class StyleRuleContainer;
class CSSContainerRule final : public CSSConditionRule {
DEFINE_WRAPPERTYPEINFO();
public:
CSSContainerRule(StyleRuleContainer*, CSSStyleSheet*);
~CSSContainerRule() override;
String cssText() const override;
private:
CSSRule::Type GetType() const override { return kContainerRule; }
};
template <>
struct DowncastTraits<CSSContainerRule> {
static bool AllowFrom(const CSSRule& rule) {
return rule.GetType() == CSSRule::kContainerRule;
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_CONTAINER_RULE_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
Exposed=Window,
RuntimeEnabled=CSSContainerQueries
] interface CSSContainerRule : CSSConditionRule {
// TODO(crbug.com/1145970): Spec and implement.
};
...@@ -32,7 +32,7 @@ namespace blink { ...@@ -32,7 +32,7 @@ namespace blink {
class ExceptionState; class ExceptionState;
class CSSRuleList; class CSSRuleList;
class CSSGroupingRule : public CSSRule { class CORE_EXPORT CSSGroupingRule : public CSSRule {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
......
...@@ -64,6 +64,7 @@ class CORE_EXPORT CSSRule : public ScriptWrappable { ...@@ -64,6 +64,7 @@ class CORE_EXPORT CSSRule : public ScriptWrappable {
// Values for internal use, not web-exposed: // Values for internal use, not web-exposed:
kPropertyRule = 16, kPropertyRule = 16,
kScrollTimelineRule = 17, kScrollTimelineRule = 17,
kContainerRule = 18,
}; };
virtual Type GetType() const = 0; virtual Type GetType() const = 0;
......
...@@ -38,9 +38,7 @@ TestStyleSheet::~TestStyleSheet() = default; ...@@ -38,9 +38,7 @@ TestStyleSheet::~TestStyleSheet() = default;
TestStyleSheet::TestStyleSheet() { TestStyleSheet::TestStyleSheet() {
document_ = Document::CreateForTest(); document_ = Document::CreateForTest();
TextPosition position; style_sheet_ = CreateStyleSheet(*document_);
style_sheet_ = CSSStyleSheet::CreateInline(*document_, NullURL(), position,
UTF8Encoding());
} }
CSSRuleList* TestStyleSheet::CssRules() { CSSRuleList* TestStyleSheet::CssRules() {
...@@ -67,6 +65,12 @@ void TestStyleSheet::AddCSSRules(const String& css_text, bool is_empty_sheet) { ...@@ -67,6 +65,12 @@ void TestStyleSheet::AddCSSRules(const String& css_text, bool is_empty_sheet) {
ASSERT_EQ(style_sheet_->length(), sheet_length); ASSERT_EQ(style_sheet_->length(), sheet_length);
} }
CSSStyleSheet* CreateStyleSheet(Document& document) {
TextPosition position;
return CSSStyleSheet::CreateInline(document, NullURL(), position,
UTF8Encoding());
}
PropertyRegistration* CreatePropertyRegistration(const String& name) { PropertyRegistration* CreatePropertyRegistration(const String& name) {
auto syntax_definition = CSSSyntaxStringParser("*").Parse(); auto syntax_definition = CSSSyntaxStringParser("*").Parse();
DCHECK(syntax_definition); DCHECK(syntax_definition);
......
...@@ -45,6 +45,8 @@ class TestStyleSheet { ...@@ -45,6 +45,8 @@ class TestStyleSheet {
Persistent<CSSStyleSheet> style_sheet_; Persistent<CSSStyleSheet> style_sheet_;
}; };
CSSStyleSheet* CreateStyleSheet(Document& document);
// Create a PropertyRegistration for the given name. The syntax, initial value, // Create a PropertyRegistration for the given name. The syntax, initial value,
// and inherited status are all undefined. // and inherited status are all undefined.
PropertyRegistration* CreatePropertyRegistration(const String& name); PropertyRegistration* CreatePropertyRegistration(const String& name);
......
...@@ -179,6 +179,7 @@ CSSValue* ConsumeDescriptor(StyleRule::RuleType rule_type, ...@@ -179,6 +179,7 @@ CSSValue* ConsumeDescriptor(StyleRule::RuleType rule_type,
case StyleRule::kScrollTimeline: case StyleRule::kScrollTimeline:
return Parser::ParseAtScrollTimelineDescriptor(id, range, context); return Parser::ParseAtScrollTimelineDescriptor(id, range, context);
case StyleRule::kCharset: case StyleRule::kCharset:
case StyleRule::kContainer:
case StyleRule::kStyle: case StyleRule::kStyle:
case StyleRule::kImport: case StyleRule::kImport:
case StyleRule::kMedia: case StyleRule::kMedia:
......
...@@ -27,6 +27,11 @@ CSSAtRuleID CssAtRuleID(StringView name) { ...@@ -27,6 +27,11 @@ CSSAtRuleID CssAtRuleID(StringView name) {
return kCSSAtRulePage; return kCSSAtRulePage;
if (EqualIgnoringASCIICase(name, "property")) if (EqualIgnoringASCIICase(name, "property"))
return kCSSAtRuleProperty; return kCSSAtRuleProperty;
if (EqualIgnoringASCIICase(name, "container")) {
if (RuntimeEnabledFeatures::CSSContainerQueriesEnabled())
return kCSSAtRuleContainer;
return kCSSAtRuleInvalid;
}
if (EqualIgnoringASCIICase(name, "counter-style")) { if (EqualIgnoringASCIICase(name, "counter-style")) {
if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled()) if (RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled())
return kCSSAtRuleCounterStyle; return kCSSAtRuleCounterStyle;
...@@ -74,6 +79,9 @@ void CountAtRule(const CSSParserContext* context, CSSAtRuleID rule_id) { ...@@ -74,6 +79,9 @@ void CountAtRule(const CSSParserContext* context, CSSAtRuleID rule_id) {
case kCSSAtRuleProperty: case kCSSAtRuleProperty:
feature = WebFeature::kCSSAtRuleProperty; feature = WebFeature::kCSSAtRuleProperty;
break; break;
case kCSSAtRuleContainer:
// TODO(crbug.com/1145970): Add use-counter.
return;
case kCSSAtRuleCounterStyle: case kCSSAtRuleCounterStyle:
// TODO(crbug.com/687225): Add feature counter // TODO(crbug.com/687225): Add feature counter
return; return;
......
...@@ -21,6 +21,7 @@ enum CSSAtRuleID { ...@@ -21,6 +21,7 @@ enum CSSAtRuleID {
kCSSAtRuleNamespace, kCSSAtRuleNamespace,
kCSSAtRulePage, kCSSAtRulePage,
kCSSAtRuleProperty, kCSSAtRuleProperty,
kCSSAtRuleContainer,
kCSSAtRuleCounterStyle, kCSSAtRuleCounterStyle,
kCSSAtRuleScrollTimeline, kCSSAtRuleScrollTimeline,
kCSSAtRuleSupports, kCSSAtRuleSupports,
......
...@@ -546,6 +546,8 @@ StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenStream& stream, ...@@ -546,6 +546,8 @@ StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenStream& stream,
DCHECK_LE(allowed_rules, kRegularRules); DCHECK_LE(allowed_rules, kRegularRules);
switch (id) { switch (id) {
case kCSSAtRuleContainer:
return ConsumeContainerRule(stream);
case kCSSAtRuleMedia: case kCSSAtRuleMedia:
return ConsumeMediaRule(stream); return ConsumeMediaRule(stream);
case kCSSAtRuleSupports: case kCSSAtRuleSupports:
...@@ -996,6 +998,40 @@ StyleRuleScrollTimeline* CSSParserImpl::ConsumeScrollTimelineRule( ...@@ -996,6 +998,40 @@ StyleRuleScrollTimeline* CSSParserImpl::ConsumeScrollTimelineRule(
name, CreateCSSPropertyValueSet(parsed_properties_, context_->Mode())); name, CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
} }
StyleRuleContainer* CSSParserImpl::ConsumeContainerRule(
CSSParserTokenStream& stream) {
wtf_size_t prelude_offset_start = stream.LookAheadOffset();
CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
wtf_size_t prelude_offset_end = stream.LookAheadOffset();
if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
return nullptr;
CSSParserTokenStream::BlockGuard guard(stream);
if (observer_) {
observer_->StartRuleHeader(StyleRule::kContainer, prelude_offset_start);
observer_->EndRuleHeader(prelude_offset_end);
observer_->StartRuleBody(stream.Offset());
}
// TODO(crbug.com/1145970): Restrict what is allowed by @container.
scoped_refptr<MediaQuerySet> media_queries =
MediaQueryParser::ParseMediaQuerySet(prelude,
context_->GetExecutionContext());
if (!media_queries)
return nullptr;
ContainerQuery* container_query =
MakeGarbageCollected<ContainerQuery>(media_queries);
HeapVector<Member<StyleRuleBase>> rules;
ConsumeRuleList(stream, kRegularRuleList,
[&rules](StyleRuleBase* rule) { rules.push_back(rule); });
if (observer_)
observer_->EndRuleBody(stream.Offset());
return MakeGarbageCollected<StyleRuleContainer>(*container_query, rules);
}
StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule( StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule(
const CSSParserTokenRange prelude, const CSSParserTokenRange prelude,
const RangeOffset& prelude_offset, const RangeOffset& prelude_offset,
...@@ -1065,6 +1101,7 @@ void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenStream& stream, ...@@ -1065,6 +1101,7 @@ void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenStream& stream,
bool use_observer = observer_ && (rule_type == StyleRule::kStyle || bool use_observer = observer_ && (rule_type == StyleRule::kStyle ||
rule_type == StyleRule::kProperty || rule_type == StyleRule::kProperty ||
rule_type == StyleRule::kContainer ||
rule_type == StyleRule::kCounterStyle || rule_type == StyleRule::kCounterStyle ||
rule_type == StyleRule::kScrollTimeline || rule_type == StyleRule::kScrollTimeline ||
rule_type == StyleRule::kKeyframe); rule_type == StyleRule::kKeyframe);
......
...@@ -168,6 +168,7 @@ class CORE_EXPORT CSSParserImpl { ...@@ -168,6 +168,7 @@ class CORE_EXPORT CSSParserImpl {
StyleRuleProperty* ConsumePropertyRule(CSSParserTokenStream&); StyleRuleProperty* ConsumePropertyRule(CSSParserTokenStream&);
StyleRuleCounterStyle* ConsumeCounterStyleRule(CSSParserTokenStream&); StyleRuleCounterStyle* ConsumeCounterStyleRule(CSSParserTokenStream&);
StyleRuleScrollTimeline* ConsumeScrollTimelineRule(CSSParserTokenStream&); StyleRuleScrollTimeline* ConsumeScrollTimelineRule(CSSParserTokenStream&);
StyleRuleContainer* ConsumeContainerRule(CSSParserTokenStream&);
StyleRuleKeyframe* ConsumeKeyframeStyleRule(CSSParserTokenRange prelude, StyleRuleKeyframe* ConsumeKeyframeStyleRule(CSSParserTokenRange prelude,
const RangeOffset& prelude_offset, const RangeOffset& prelude_offset,
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_observer.h" #include "third_party/blink/renderer/core/css/parser/css_parser_observer.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h" #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h" #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink { namespace blink {
...@@ -225,6 +227,40 @@ TEST(CSSParserImplTest, AtCounterStyleDisabled) { ...@@ -225,6 +227,40 @@ TEST(CSSParserImplTest, AtCounterStyleDisabled) {
EXPECT_EQ(style_sheet->ChildRules().size(), 0u); EXPECT_EQ(style_sheet->ChildRules().size(), 0u);
} }
TEST(CSSParserImplTest, AtContainerOffsets) {
ScopedCSSContainerQueriesForTest scoped_feature(true);
String sheet_text = "@container (max-width: 100px) { }";
auto* context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(context);
TestCSSParserObserver test_css_parser_observer;
CSSParserImpl::ParseStyleSheetForInspector(sheet_text, context, style_sheet,
test_css_parser_observer);
EXPECT_EQ(style_sheet->ChildRules().size(), 1u);
EXPECT_EQ(test_css_parser_observer.rule_type_,
StyleRule::RuleType::kContainer);
EXPECT_EQ(test_css_parser_observer.rule_header_start_, 11u);
EXPECT_EQ(test_css_parser_observer.rule_header_end_, 30u);
EXPECT_EQ(test_css_parser_observer.rule_body_start_, 31u);
EXPECT_EQ(test_css_parser_observer.rule_body_end_, 32u);
}
TEST(CSSParserImplTest, AtContainerDisabled) {
String rule = "@container (max-width: 100px) { }";
{
ScopedCSSContainerQueriesForTest scoped_feature(true);
Document* document = Document::CreateForTest();
EXPECT_TRUE(css_test_helpers::ParseRule(*document, rule));
}
{
ScopedCSSContainerQueriesForTest scoped_feature(false);
Document* document = Document::CreateForTest();
EXPECT_FALSE(css_test_helpers::ParseRule(*document, rule));
}
}
TEST(CSSParserImplTest, RemoveImportantAnnotationIfPresent) { TEST(CSSParserImplTest, RemoveImportantAnnotationIfPresent) {
struct TestCase { struct TestCase {
String input; String input;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/css_container_rule.h"
#include "third_party/blink/renderer/core/css/css_counter_style_rule.h" #include "third_party/blink/renderer/core/css/css_counter_style_rule.h"
#include "third_party/blink/renderer/core/css/css_font_face_rule.h" #include "third_party/blink/renderer/core/css/css_font_face_rule.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h"
...@@ -97,6 +98,9 @@ void StyleRuleBase::Trace(Visitor* visitor) const { ...@@ -97,6 +98,9 @@ void StyleRuleBase::Trace(Visitor* visitor) const {
case kViewport: case kViewport:
To<StyleRuleViewport>(this)->TraceAfterDispatch(visitor); To<StyleRuleViewport>(this)->TraceAfterDispatch(visitor);
return; return;
case kContainer:
To<StyleRuleContainer>(this)->TraceAfterDispatch(visitor);
return;
case kCounterStyle: case kCounterStyle:
To<StyleRuleCounterStyle>(this)->TraceAfterDispatch(visitor); To<StyleRuleCounterStyle>(this)->TraceAfterDispatch(visitor);
return; return;
...@@ -145,6 +149,9 @@ void StyleRuleBase::FinalizeGarbageCollectedObject() { ...@@ -145,6 +149,9 @@ void StyleRuleBase::FinalizeGarbageCollectedObject() {
case kViewport: case kViewport:
To<StyleRuleViewport>(this)->~StyleRuleViewport(); To<StyleRuleViewport>(this)->~StyleRuleViewport();
return; return;
case kContainer:
To<StyleRuleContainer>(this)->~StyleRuleContainer();
return;
case kCounterStyle: case kCounterStyle:
To<StyleRuleCounterStyle>(this)->~StyleRuleCounterStyle(); To<StyleRuleCounterStyle>(this)->~StyleRuleCounterStyle();
return; return;
...@@ -182,6 +189,8 @@ StyleRuleBase* StyleRuleBase::Copy() const { ...@@ -182,6 +189,8 @@ StyleRuleBase* StyleRuleBase::Copy() const {
case kKeyframe: case kKeyframe:
NOTREACHED(); NOTREACHED();
return nullptr; return nullptr;
case kContainer:
return To<StyleRuleContainer>(this)->Copy();
case kCounterStyle: case kCounterStyle:
return To<StyleRuleCounterStyle>(this)->Copy(); return To<StyleRuleCounterStyle>(this)->Copy();
} }
...@@ -234,6 +243,10 @@ CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet, ...@@ -234,6 +243,10 @@ CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet,
rule = MakeGarbageCollected<CSSNamespaceRule>( rule = MakeGarbageCollected<CSSNamespaceRule>(
To<StyleRuleNamespace>(self), parent_sheet); To<StyleRuleNamespace>(self), parent_sheet);
break; break;
case kContainer:
rule = MakeGarbageCollected<CSSContainerRule>(
To<StyleRuleContainer>(self), parent_sheet);
break;
case kCounterStyle: case kCounterStyle:
rule = MakeGarbageCollected<CSSCounterStyleRule>( rule = MakeGarbageCollected<CSSCounterStyleRule>(
To<StyleRuleCounterStyle>(self), parent_sheet); To<StyleRuleCounterStyle>(self), parent_sheet);
...@@ -480,6 +493,24 @@ StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& supports_rule) ...@@ -480,6 +493,24 @@ StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& supports_rule)
: StyleRuleCondition(supports_rule), : StyleRuleCondition(supports_rule),
condition_is_supported_(supports_rule.condition_is_supported_) {} condition_is_supported_(supports_rule.condition_is_supported_) {}
StyleRuleContainer::StyleRuleContainer(
ContainerQuery& container_query,
HeapVector<Member<StyleRuleBase>>& adopt_rules)
: StyleRuleCondition(kContainer, adopt_rules),
container_query_(&container_query) {}
StyleRuleContainer::StyleRuleContainer(const StyleRuleContainer& container_rule)
: StyleRuleCondition(container_rule) {
DCHECK(container_rule.container_query_);
container_query_ =
MakeGarbageCollected<ContainerQuery>(*container_rule.container_query_);
}
void StyleRuleContainer::TraceAfterDispatch(blink::Visitor* visitor) const {
visitor->Trace(container_query_);
StyleRuleCondition::TraceAfterDispatch(visitor);
}
StyleRuleViewport::StyleRuleViewport(CSSPropertyValueSet* properties) StyleRuleViewport::StyleRuleViewport(CSSPropertyValueSet* properties)
: StyleRuleBase(kViewport), properties_(properties) {} : StyleRuleBase(kViewport), properties_(properties) {}
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/container_query.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_selector_list.h" #include "third_party/blink/renderer/core/css/css_selector_list.h"
#include "third_party/blink/renderer/core/css/media_list.h" #include "third_party/blink/renderer/core/css/media_list.h"
...@@ -48,6 +49,7 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> { ...@@ -48,6 +49,7 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
kKeyframes, kKeyframes,
kKeyframe, kKeyframe,
kNamespace, kNamespace,
kContainer,
kCounterStyle, kCounterStyle,
kScrollTimeline, kScrollTimeline,
kSupports, kSupports,
...@@ -57,6 +59,7 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> { ...@@ -57,6 +59,7 @@ class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
RuleType GetType() const { return static_cast<RuleType>(type_); } RuleType GetType() const { return static_cast<RuleType>(type_); }
bool IsCharsetRule() const { return GetType() == kCharset; } bool IsCharsetRule() const { return GetType() == kCharset; }
bool IsContainerRule() const { return GetType() == kContainer; }
bool IsCounterStyleRule() const { return GetType() == kCounterStyle; } bool IsCounterStyleRule() const { return GetType() == kCounterStyle; }
bool IsFontFaceRule() const { return GetType() == kFontFace; } bool IsFontFaceRule() const { return GetType() == kFontFace; }
bool IsKeyframesRule() const { return GetType() == kKeyframes; } bool IsKeyframesRule() const { return GetType() == kKeyframes; }
...@@ -317,6 +320,24 @@ class StyleRuleSupports : public StyleRuleCondition { ...@@ -317,6 +320,24 @@ class StyleRuleSupports : public StyleRuleCondition {
bool condition_is_supported_; bool condition_is_supported_;
}; };
class CORE_EXPORT StyleRuleContainer : public StyleRuleCondition {
public:
StyleRuleContainer(ContainerQuery&,
HeapVector<Member<StyleRuleBase>>& adopt_rules);
StyleRuleContainer(const StyleRuleContainer&);
ContainerQuery& GetContainerQuery() const { return *container_query_; }
StyleRuleContainer* Copy() const {
return MakeGarbageCollected<StyleRuleContainer>(*this);
}
void TraceAfterDispatch(blink::Visitor*) const;
private:
Member<ContainerQuery> container_query_;
};
class StyleRuleViewport : public StyleRuleBase { class StyleRuleViewport : public StyleRuleBase {
public: public:
explicit StyleRuleViewport(CSSPropertyValueSet*); explicit StyleRuleViewport(CSSPropertyValueSet*);
...@@ -379,6 +400,14 @@ struct DowncastTraits<StyleRuleScrollTimeline> { ...@@ -379,6 +400,14 @@ struct DowncastTraits<StyleRuleScrollTimeline> {
} }
}; };
template <>
struct DowncastTraits<StyleRuleGroup> {
static bool AllowFrom(const StyleRuleBase& rule) {
return rule.IsMediaRule() || rule.IsSupportsRule() ||
rule.IsContainerRule();
}
};
template <> template <>
struct DowncastTraits<StyleRuleMedia> { struct DowncastTraits<StyleRuleMedia> {
static bool AllowFrom(const StyleRuleBase& rule) { static bool AllowFrom(const StyleRuleBase& rule) {
...@@ -393,6 +422,13 @@ struct DowncastTraits<StyleRuleSupports> { ...@@ -393,6 +422,13 @@ struct DowncastTraits<StyleRuleSupports> {
} }
}; };
template <>
struct DowncastTraits<StyleRuleContainer> {
static bool AllowFrom(const StyleRuleBase& rule) {
return rule.IsContainerRule();
}
};
template <> template <>
struct DowncastTraits<StyleRuleViewport> { struct DowncastTraits<StyleRuleViewport> {
static bool AllowFrom(const StyleRuleBase& rule) { static bool AllowFrom(const StyleRuleBase& rule) {
......
...@@ -491,9 +491,10 @@ static bool ChildRulesHaveFailedOrCanceledSubresources( ...@@ -491,9 +491,10 @@ static bool ChildRulesHaveFailedOrCanceledSubresources(
.HasFailedOrCanceledSubresources()) .HasFailedOrCanceledSubresources())
return true; return true;
break; break;
case StyleRuleBase::kContainer:
case StyleRuleBase::kMedia: case StyleRuleBase::kMedia:
if (ChildRulesHaveFailedOrCanceledSubresources( if (ChildRulesHaveFailedOrCanceledSubresources(
To<StyleRuleMedia>(rule)->ChildRules())) To<StyleRuleGroup>(rule)->ChildRules()))
return true; return true;
break; break;
case StyleRuleBase::kCharset: case StyleRuleBase::kCharset:
......
...@@ -506,7 +506,8 @@ void FrameSerializer::SerializeCSSRule(CSSRule* rule) { ...@@ -506,7 +506,8 @@ void FrameSerializer::SerializeCSSRule(CSSRule* rule) {
// Rules inheriting CSSGroupingRule // Rules inheriting CSSGroupingRule
case CSSRule::kMediaRule: case CSSRule::kMediaRule:
case CSSRule::kSupportsRule: { case CSSRule::kSupportsRule:
case CSSRule::kContainerRule: {
CSSRuleList* rule_list = rule->cssRules(); CSSRuleList* rule_list = rule->cssRules();
for (unsigned i = 0; i < rule_list->length(); ++i) for (unsigned i = 0; i < rule_list->length(); ++i)
SerializeCSSRule(rule_list->item(i)); SerializeCSSRule(rule_list->item(i));
......
...@@ -462,6 +462,9 @@ ...@@ -462,6 +462,9 @@
// rendering for form controls, scrollbars, etc. // rendering for form controls, scrollbars, etc.
name: "CSSColorSchemeUARendering", name: "CSSColorSchemeUARendering",
}, },
{
name: "CSSContainerQueries",
},
{ {
// The main content-visibility feature. // The main content-visibility feature.
// https://drafts.csswg.org/css-contain/#content-visibility // https://drafts.csswg.org/css-contain/#content-visibility
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment