1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/core/css/resolver/style_cascade.h"
6
7 #include <vector>
8
9 #include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet_init.h"
10 #include "third_party/blink/renderer/core/animation/css/css_animations.h"
11 #include "third_party/blink/renderer/core/css/active_style_sheets.h"
12 #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
13 #include "third_party/blink/renderer/core/css/css_initial_color_value.h"
14 #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
15 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
16 #include "third_party/blink/renderer/core/css/css_revert_value.h"
17 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
18 #include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
19 #include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
20 #include "third_party/blink/renderer/core/css/media_query_evaluator.h"
21 #include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
22 #include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
23 #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
24 #include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
25 #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
26 #include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
27 #include "third_party/blink/renderer/core/css/properties/css_property_instances.h"
28 #include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
29 #include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
30 #include "third_party/blink/renderer/core/css/property_registry.h"
31 #include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
32 #include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h"
33 #include "third_party/blink/renderer/core/css/resolver/cascade_map.h"
34 #include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
35 #include "third_party/blink/renderer/core/css/resolver/cascade_resolver.h"
36 #include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h"
37 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
38 #include "third_party/blink/renderer/core/css/style_engine.h"
39 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
40 #include "third_party/blink/renderer/core/html/html_element.h"
41 #include "third_party/blink/renderer/core/style/computed_style.h"
42 #include "third_party/blink/renderer/core/style_property_shorthand.h"
43 #include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
44 #include "third_party/blink/renderer/core/testing/page_test_base.h"
45 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
46 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
47
48 namespace blink {
49
50 using css_test_helpers::ParseDeclarationBlock;
51 using css_test_helpers::RegisterProperty;
52 using Origin = CascadeOrigin;
53 using Priority = CascadePriority;
54 using UnitType = CSSPrimitiveValue::UnitType;
55
56 class TestCascadeResolver {
57 STACK_ALLOCATED();
58
59 public:
TestCascadeResolver(uint8_t generation=0)60 explicit TestCascadeResolver(uint8_t generation = 0)
61 : resolver_(CascadeFilter(), generation) {}
InCycle() const62 bool InCycle() const { return resolver_.InCycle(); }
DetectCycle(const CSSProperty & property)63 bool DetectCycle(const CSSProperty& property) {
64 return resolver_.DetectCycle(property);
65 }
CycleDepth() const66 wtf_size_t CycleDepth() const { return resolver_.cycle_depth_; }
MarkApplied(CascadePriority * priority)67 void MarkApplied(CascadePriority* priority) {
68 resolver_.MarkApplied(priority);
69 }
MarkUnapplied(CascadePriority * priority)70 void MarkUnapplied(CascadePriority* priority) {
71 resolver_.MarkUnapplied(priority);
72 }
GetGeneration()73 uint8_t GetGeneration() { return resolver_.generation_; }
InnerResolver()74 CascadeResolver& InnerResolver() { return resolver_; }
CurrentProperty() const75 const CSSProperty* CurrentProperty() const {
76 return resolver_.CurrentProperty();
77 }
78
79 private:
80 friend class TestCascadeAutoLock;
81
82 CascadeResolver resolver_;
83 };
84
85 class TestCascade {
86 STACK_ALLOCATED();
87
88 public:
TestCascade(Document & document,Element * target=nullptr)89 TestCascade(Document& document, Element* target = nullptr)
90 : state_(document, target ? *target : *document.body()),
91 cascade_(InitState(state_)) {}
92
TakeStyle()93 scoped_refptr<ComputedStyle> TakeStyle() { return state_.TakeStyle(); }
94
State()95 StyleResolverState& State() { return state_; }
InnerCascade()96 StyleCascade& InnerCascade() { return cascade_; }
97
InheritFrom(scoped_refptr<ComputedStyle> parent)98 void InheritFrom(scoped_refptr<ComputedStyle> parent) {
99 state_.SetParentStyle(parent);
100 state_.StyleRef().InheritFrom(*parent);
101 }
102
103 // Note that because of how MatchResult works, declarations must be added
104 // in "origin order", i.e. UserAgent first, then User, then Author.
105
Add(String block,CascadeOrigin origin=CascadeOrigin::kAuthor,unsigned link_match_type=CSSSelector::kMatchAll)106 void Add(String block,
107 CascadeOrigin origin = CascadeOrigin::kAuthor,
108 unsigned link_match_type = CSSSelector::kMatchAll) {
109 CSSParserMode mode =
110 origin == CascadeOrigin::kUserAgent ? kUASheetMode : kHTMLStandardMode;
111 Add(ParseDeclarationBlock(block, mode), origin, link_match_type);
112 }
113
Add(String name,String value,CascadeOrigin origin=Origin::kAuthor)114 void Add(String name, String value, CascadeOrigin origin = Origin::kAuthor) {
115 Add(name + ":" + value, origin);
116 }
117
Add(const CSSPropertyValueSet * set,CascadeOrigin origin=CascadeOrigin::kAuthor,unsigned link_match_type=CSSSelector::kMatchAll)118 void Add(const CSSPropertyValueSet* set,
119 CascadeOrigin origin = CascadeOrigin::kAuthor,
120 unsigned link_match_type = CSSSelector::kMatchAll) {
121 DCHECK_LE(origin, CascadeOrigin::kAuthor) << "Animations not supported";
122 DCHECK_LE(current_origin_, origin) << "Please add declarations in order";
123 EnsureAtLeast(origin);
124 cascade_.MutableMatchResult().AddMatchedProperties(set, link_match_type);
125 }
126
Apply(CascadeFilter filter=CascadeFilter ())127 void Apply(CascadeFilter filter = CascadeFilter()) {
128 EnsureAtLeast(CascadeOrigin::kAnimation);
129 cascade_.Apply(filter);
130 }
131
ApplySingle(const CSSProperty & property)132 void ApplySingle(const CSSProperty& property) {
133 EnsureAtLeast(CascadeOrigin::kAnimation);
134 cascade_.AnalyzeIfNeeded();
135 TestCascadeResolver resolver(++cascade_.generation_);
136 cascade_.LookupAndApply(property, resolver.InnerResolver());
137 }
138
AnalyzeIfNeeded()139 void AnalyzeIfNeeded() { cascade_.AnalyzeIfNeeded(); }
140
Resolve(const CSSProperty & property,const CSSValue & value,CascadeOrigin & origin)141 const CSSValue* Resolve(const CSSProperty& property,
142 const CSSValue& value,
143 CascadeOrigin& origin) {
144 TestCascadeResolver resolver;
145 return cascade_.Resolve(property, value, origin, resolver.InnerResolver());
146 }
147
GetImportantSet()148 std::unique_ptr<CSSBitset> GetImportantSet() {
149 return cascade_.GetImportantSet();
150 }
151
ComputedValue(String name) const152 String ComputedValue(String name) const {
153 CSSPropertyRef ref(name, GetDocument());
154 DCHECK(ref.IsValid());
155 const LayoutObject* layout_object = nullptr;
156 bool allow_visited_style = false;
157 const CSSValue* value = ref.GetProperty().CSSValueFromComputedStyle(
158 *state_.Style(), layout_object, allow_visited_style);
159 return value ? value->CssText() : g_null_atom;
160 }
161
GetPriority(String name)162 CascadePriority GetPriority(String name) {
163 return GetPriority(
164 *CSSPropertyName::From(GetDocument().GetExecutionContext(), name));
165 }
166
GetPriority(CSSPropertyName name)167 CascadePriority GetPriority(CSSPropertyName name) {
168 CascadePriority* c = cascade_.map_.Find(name);
169 return c ? *c : CascadePriority();
170 }
171
GetOrigin(String name)172 CascadeOrigin GetOrigin(String name) { return GetPriority(name).GetOrigin(); }
173
CalculateTransitionUpdate()174 void CalculateTransitionUpdate() {
175 CSSAnimations::CalculateTransitionUpdate(
176 state_.AnimationUpdate(), CSSAnimations::PropertyPass::kCustom,
177 &state_.GetElement(), *state_.Style());
178 CSSAnimations::CalculateTransitionUpdate(
179 state_.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard,
180 &state_.GetElement(), *state_.Style());
181 AddTransitions();
182 }
183
CalculateAnimationUpdate()184 void CalculateAnimationUpdate() {
185 CSSAnimations::CalculateAnimationUpdate(
186 state_.AnimationUpdate(), &state_.GetElement(), state_.GetElement(),
187 *state_.Style(), state_.ParentStyle(),
188 &GetDocument().GetStyleResolver());
189 AddAnimations();
190 }
191
Reset()192 void Reset() {
193 cascade_.Reset();
194 current_origin_ = CascadeOrigin::kUserAgent;
195 }
196
NeedsMatchResultAnalyze() const197 bool NeedsMatchResultAnalyze() const {
198 return cascade_.needs_match_result_analyze_;
199 }
NeedsInterpolationsAnalyze() const200 bool NeedsInterpolationsAnalyze() const {
201 return cascade_.needs_interpolations_analyze_;
202 }
DependsOnCascadeAffectingProperty() const203 bool DependsOnCascadeAffectingProperty() const {
204 return cascade_.depends_on_cascade_affecting_property_;
205 }
206
GetCascadedValues() const207 HeapHashMap<CSSPropertyName, Member<const CSSValue>> GetCascadedValues()
208 const {
209 return cascade_.GetCascadedValues();
210 }
211
212 private:
GetDocument() const213 Document& GetDocument() const { return state_.GetDocument(); }
Body() const214 Element* Body() const { return GetDocument().body(); }
215
InitState(StyleResolverState & state)216 static StyleResolverState& InitState(StyleResolverState& state) {
217 state.SetStyle(InitialStyle(state.GetDocument()));
218 state.SetParentStyle(InitialStyle(state.GetDocument()));
219 return state;
220 }
221
InitialStyle(Document & document)222 static scoped_refptr<ComputedStyle> InitialStyle(Document& document) {
223 return StyleResolver::InitialStyleForElement(document);
224 }
225
FinishOrigin()226 void FinishOrigin() {
227 switch (current_origin_) {
228 case CascadeOrigin::kUserAgent:
229 cascade_.MutableMatchResult().FinishAddingUARules();
230 current_origin_ = CascadeOrigin::kUser;
231 break;
232 case CascadeOrigin::kUser:
233 cascade_.MutableMatchResult().FinishAddingUserRules();
234 current_origin_ = CascadeOrigin::kAuthor;
235 break;
236 case CascadeOrigin::kAuthor:
237 cascade_.MutableMatchResult().FinishAddingAuthorRulesForTreeScope(
238 GetDocument());
239 current_origin_ = CascadeOrigin::kAnimation;
240 break;
241 case CascadeOrigin::kAnimation:
242 break;
243 default:
244 NOTREACHED();
245 break;
246 }
247 }
248
EnsureAtLeast(CascadeOrigin origin)249 void EnsureAtLeast(CascadeOrigin origin) {
250 while (current_origin_ < origin)
251 FinishOrigin();
252 }
253
AddAnimations()254 void AddAnimations() {
255 const auto& update = state_.AnimationUpdate();
256 if (update.IsEmpty())
257 return;
258 cascade_.AddInterpolations(
259 &update.ActiveInterpolationsForCustomAnimations(),
260 CascadeOrigin::kAnimation);
261 cascade_.AddInterpolations(
262 &update.ActiveInterpolationsForStandardAnimations(),
263 CascadeOrigin::kAnimation);
264 }
265
AddTransitions()266 void AddTransitions() {
267 const auto& update = state_.AnimationUpdate();
268 if (update.IsEmpty())
269 return;
270 cascade_.AddInterpolations(
271 &update.ActiveInterpolationsForCustomTransitions(),
272 CascadeOrigin::kTransition);
273 cascade_.AddInterpolations(
274 &update.ActiveInterpolationsForStandardTransitions(),
275 CascadeOrigin::kTransition);
276 }
277
278 CascadeOrigin current_origin_ = CascadeOrigin::kUserAgent;
279 StyleResolverState state_;
280 StyleCascade cascade_;
281 };
282
283 class TestCascadeAutoLock {
284 STACK_ALLOCATED();
285
286 public:
TestCascadeAutoLock(const CSSProperty & property,TestCascadeResolver & resolver)287 TestCascadeAutoLock(const CSSProperty& property,
288 TestCascadeResolver& resolver)
289 : lock_(property, resolver.resolver_) {}
290
291 private:
292 CascadeResolver::AutoLock lock_;
293 };
294
295 class StyleCascadeTest
296 : public PageTestBase,
297 private ScopedCSSMatchedPropertiesCacheDependenciesForTest {
298 public:
StyleCascadeTest()299 StyleCascadeTest()
300 : ScopedCSSMatchedPropertiesCacheDependenciesForTest(true) {}
301
CreateSheet(const String & css_text)302 CSSStyleSheet* CreateSheet(const String& css_text) {
303 auto* init = MakeGarbageCollected<CSSStyleSheetInit>();
304 DummyExceptionStateForTesting exception_state;
305 CSSStyleSheet* sheet =
306 CSSStyleSheet::Create(GetDocument(), init, exception_state);
307 sheet->replaceSync(css_text, exception_state);
308 sheet->Contents()->EnsureRuleSet(
309 MediaQueryEvaluator(GetDocument().GetFrame()), kRuleHasNoSpecialState);
310 return sheet;
311 }
312
AppendSheet(const String & css_text)313 void AppendSheet(const String& css_text) {
314 CSSStyleSheet* sheet = CreateSheet(css_text);
315 ASSERT_TRUE(sheet);
316
317 Element* body = GetDocument().body();
318 ASSERT_TRUE(body->IsInTreeScope());
319 TreeScope& tree_scope = body->GetTreeScope();
320 ScopedStyleResolver& scoped_resolver =
321 tree_scope.EnsureScopedStyleResolver();
322 ActiveStyleSheetVector active_sheets;
323 active_sheets.push_back(
324 std::make_pair(sheet, &sheet->Contents()->GetRuleSet()));
325 scoped_resolver.AppendActiveStyleSheets(0, active_sheets);
326 GetDocument()
327 .GetStyleEngine()
328 .GetDocumentStyleSheetCollection()
329 .AppendActiveStyleSheet(active_sheets[0]);
330 }
331
DocumentElement() const332 Element* DocumentElement() const { return GetDocument().documentElement(); }
333
SetRootFont(String value)334 void SetRootFont(String value) {
335 DocumentElement()->SetInlineStyleProperty(CSSPropertyID::kFontSize, value);
336 UpdateAllLifecyclePhasesForTest();
337 }
338
AnimationTaintedSet(AtomicString name,String value)339 const MutableCSSPropertyValueSet* AnimationTaintedSet(AtomicString name,
340 String value) {
341 CSSParserMode mode = kHTMLStandardMode;
342 auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>(mode);
343 set->SetProperty(name, value, /* important */ false,
344 SecureContextMode::kSecureContext,
345 /* context_style_sheet */ nullptr,
346 /* is_animation_tainted */ true);
347 return set;
348 }
349
350 // Temporarily create a CSS Environment Variable.
351 // https://drafts.csswg.org/css-env-1/
352 class AutoEnv {
353 STACK_ALLOCATED();
354
355 public:
AutoEnv(PageTestBase & test,AtomicString name,String value)356 AutoEnv(PageTestBase& test, AtomicString name, String value)
357 : document_(&test.GetDocument()), name_(name) {
358 EnsureEnvironmentVariables().SetVariable(name, value);
359 }
~AutoEnv()360 ~AutoEnv() { EnsureEnvironmentVariables().RemoveVariable(name_); }
361
362 private:
EnsureEnvironmentVariables()363 DocumentStyleEnvironmentVariables& EnsureEnvironmentVariables() {
364 return document_->GetStyleEngine().EnsureEnvironmentVariables();
365 }
366
367 Document* document_;
368 AtomicString name_;
369 };
370
PropertyName(String name)371 CSSPropertyName PropertyName(String name) {
372 return *CSSPropertyName::From(GetDocument().GetExecutionContext(), name);
373 }
374
CssTextAt(const HeapHashMap<CSSPropertyName,Member<const CSSValue>> & map,String name)375 String CssTextAt(
376 const HeapHashMap<CSSPropertyName, Member<const CSSValue>>& map,
377 String name) {
378 const CSSValue* value = map.at(PropertyName(name));
379 return value ? value->CssText() : g_null_atom;
380 }
381 };
382
TEST_F(StyleCascadeTest,ApplySingle)383 TEST_F(StyleCascadeTest, ApplySingle) {
384 TestCascade cascade(GetDocument());
385 cascade.Add("width", "1px", CascadeOrigin::kUserAgent);
386 cascade.Add("width", "2px", CascadeOrigin::kAuthor);
387 cascade.Apply();
388
389 EXPECT_EQ("2px", cascade.ComputedValue("width"));
390 }
391
TEST_F(StyleCascadeTest,ApplyImportance)392 TEST_F(StyleCascadeTest, ApplyImportance) {
393 TestCascade cascade(GetDocument());
394 cascade.Add("width:1px !important", CascadeOrigin::kUserAgent);
395 cascade.Add("width:2px", CascadeOrigin::kAuthor);
396 cascade.Apply();
397
398 EXPECT_EQ("1px", cascade.ComputedValue("width"));
399 }
400
TEST_F(StyleCascadeTest,ApplyAll)401 TEST_F(StyleCascadeTest, ApplyAll) {
402 TestCascade cascade(GetDocument());
403 cascade.Add("width:1px", CascadeOrigin::kUserAgent);
404 cascade.Add("height:1px", CascadeOrigin::kUserAgent);
405 cascade.Add("all:initial", CascadeOrigin::kAuthor);
406 cascade.Apply();
407
408 EXPECT_EQ("auto", cascade.ComputedValue("width"));
409 EXPECT_EQ("auto", cascade.ComputedValue("height"));
410 }
411
TEST_F(StyleCascadeTest,ApplyAllImportance)412 TEST_F(StyleCascadeTest, ApplyAllImportance) {
413 TestCascade cascade(GetDocument());
414 cascade.Add("opacity:0.5", CascadeOrigin::kUserAgent);
415 cascade.Add("display:block !important", CascadeOrigin::kUserAgent);
416 cascade.Add("all:initial", CascadeOrigin::kAuthor);
417 cascade.Apply();
418
419 EXPECT_EQ("1", cascade.ComputedValue("opacity"));
420 EXPECT_EQ("block", cascade.ComputedValue("display"));
421 }
422
TEST_F(StyleCascadeTest,ApplyAllWithPhysicalLonghands)423 TEST_F(StyleCascadeTest, ApplyAllWithPhysicalLonghands) {
424 TestCascade cascade(GetDocument());
425 cascade.Add("width:1px", CascadeOrigin::kUserAgent);
426 cascade.Add("height:1px !important", CascadeOrigin::kUserAgent);
427 cascade.Add("all:initial", CascadeOrigin::kAuthor);
428 cascade.Apply();
429 EXPECT_EQ("auto", cascade.ComputedValue("width"));
430 EXPECT_EQ("1px", cascade.ComputedValue("height"));
431 }
432
TEST_F(StyleCascadeTest,ApplyCustomProperty)433 TEST_F(StyleCascadeTest, ApplyCustomProperty) {
434 TestCascade cascade(GetDocument());
435 cascade.Add("--x", " 10px ");
436 cascade.Add("--y", "nope");
437 cascade.Apply();
438
439 EXPECT_EQ(" 10px ", cascade.ComputedValue("--x"));
440 EXPECT_EQ("nope", cascade.ComputedValue("--y"));
441 }
442
TEST_F(StyleCascadeTest,ApplyGenerations)443 TEST_F(StyleCascadeTest, ApplyGenerations) {
444 TestCascade cascade(GetDocument());
445
446 cascade.Add("--x:10px");
447 cascade.Add("width:20px");
448 cascade.Apply();
449 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
450 EXPECT_EQ("20px", cascade.ComputedValue("width"));
451
452 cascade.State().StyleRef().SetWidth(Length::Auto());
453 cascade.State().StyleRef().SetVariableData("--x", nullptr, true);
454 EXPECT_EQ(g_null_atom, cascade.ComputedValue("--x"));
455 EXPECT_EQ("auto", cascade.ComputedValue("width"));
456
457 // Apply again
458 cascade.Apply();
459 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
460 EXPECT_EQ("20px", cascade.ComputedValue("width"));
461 }
462
TEST_F(StyleCascadeTest,ApplyCustomPropertyVar)463 TEST_F(StyleCascadeTest, ApplyCustomPropertyVar) {
464 // Apply --x first.
465 {
466 TestCascade cascade(GetDocument());
467 cascade.Add("--x", "yes and var(--y)");
468 cascade.Add("--y", "no");
469 cascade.Apply();
470
471 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
472 EXPECT_EQ("no", cascade.ComputedValue("--y"));
473 }
474
475 // Apply --y first.
476 {
477 TestCascade cascade(GetDocument());
478 cascade.Add("--y", "no");
479 cascade.Add("--x", "yes and var(--y)");
480 cascade.Apply();
481
482 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
483 EXPECT_EQ("no", cascade.ComputedValue("--y"));
484 }
485 }
486
TEST_F(StyleCascadeTest,InvalidVarReferenceCauseInvalidVariable)487 TEST_F(StyleCascadeTest, InvalidVarReferenceCauseInvalidVariable) {
488 TestCascade cascade(GetDocument());
489 cascade.Add("--x", "nope var(--y)");
490 cascade.Apply();
491
492 EXPECT_EQ(g_null_atom, cascade.ComputedValue("--x"));
493 }
494
TEST_F(StyleCascadeTest,ApplyCustomPropertyFallback)495 TEST_F(StyleCascadeTest, ApplyCustomPropertyFallback) {
496 TestCascade cascade(GetDocument());
497 cascade.Add("--x", "yes and var(--y,no)");
498 cascade.Apply();
499
500 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
501 }
502
TEST_F(StyleCascadeTest,RegisteredPropertyFallback)503 TEST_F(StyleCascadeTest, RegisteredPropertyFallback) {
504 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
505
506 TestCascade cascade(GetDocument());
507 cascade.Add("--x", "var(--y,10px)");
508 cascade.Apply();
509
510 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
511 }
512
TEST_F(StyleCascadeTest,RegisteredPropertyFallbackValidation)513 TEST_F(StyleCascadeTest, RegisteredPropertyFallbackValidation) {
514 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
515
516 TestCascade cascade(GetDocument());
517 cascade.Add("--x", "10px");
518 cascade.Add("--y", "var(--x,red)"); // Fallback must be valid <length>.
519 cascade.Add("--z", "var(--y,pass)");
520 cascade.Apply();
521
522 EXPECT_EQ("pass", cascade.ComputedValue("--z"));
523 }
524
TEST_F(StyleCascadeTest,VarInFallback)525 TEST_F(StyleCascadeTest, VarInFallback) {
526 TestCascade cascade(GetDocument());
527 cascade.Add("--x", "one var(--z,two var(--y))");
528 cascade.Add("--y", "three");
529 cascade.Apply();
530
531 EXPECT_EQ("one two three", cascade.ComputedValue("--x"));
532 }
533
TEST_F(StyleCascadeTest,VarReferenceInNormalProperty)534 TEST_F(StyleCascadeTest, VarReferenceInNormalProperty) {
535 TestCascade cascade(GetDocument());
536 cascade.Add("--x", "10px");
537 cascade.Add("width", "var(--x)");
538 cascade.Apply();
539
540 EXPECT_EQ("10px", cascade.ComputedValue("width"));
541 }
542
TEST_F(StyleCascadeTest,MultipleVarRefs)543 TEST_F(StyleCascadeTest, MultipleVarRefs) {
544 TestCascade cascade(GetDocument());
545 cascade.Add("--x", "var(--y) bar var(--y)");
546 cascade.Add("--y", "foo");
547 cascade.Apply();
548
549 EXPECT_EQ("foo bar foo", cascade.ComputedValue("--x"));
550 }
551
TEST_F(StyleCascadeTest,RegisteredPropertyComputedValue)552 TEST_F(StyleCascadeTest, RegisteredPropertyComputedValue) {
553 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
554
555 TestCascade cascade(GetDocument());
556 cascade.Add("--x", "1in");
557 cascade.Apply();
558
559 EXPECT_EQ("96px", cascade.ComputedValue("--x"));
560 }
561
TEST_F(StyleCascadeTest,RegisteredPropertySyntaxErrorCausesInitial)562 TEST_F(StyleCascadeTest, RegisteredPropertySyntaxErrorCausesInitial) {
563 RegisterProperty(GetDocument(), "--x", "<length>", "10px", false);
564
565 TestCascade cascade(GetDocument());
566 cascade.Add("--x", "#fefefe");
567 cascade.Add("--y", "var(--x)");
568 cascade.Apply();
569
570 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
571 EXPECT_EQ("10px", cascade.ComputedValue("--y"));
572 }
573
TEST_F(StyleCascadeTest,RegisteredPropertySubstitution)574 TEST_F(StyleCascadeTest, RegisteredPropertySubstitution) {
575 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
576
577 TestCascade cascade(GetDocument());
578 cascade.Add("--x", "1in");
579 cascade.Add("--y", "var(--x)");
580 cascade.Apply();
581
582 EXPECT_EQ("96px", cascade.ComputedValue("--y"));
583 }
584
TEST_F(StyleCascadeTest,RegisteredPropertyChain)585 TEST_F(StyleCascadeTest, RegisteredPropertyChain) {
586 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
587 RegisterProperty(GetDocument(), "--z", "<length>", "0px", false);
588
589 TestCascade cascade(GetDocument());
590 cascade.Add("--x", "1in");
591 cascade.Add("--y", "var(--x)");
592 cascade.Add("--z", "calc(var(--y) + 1in)");
593 cascade.Apply();
594
595 EXPECT_EQ("96px", cascade.ComputedValue("--x"));
596 EXPECT_EQ("96px", cascade.ComputedValue("--y"));
597 EXPECT_EQ("192px", cascade.ComputedValue("--z"));
598 }
599
TEST_F(StyleCascadeTest,BasicShorthand)600 TEST_F(StyleCascadeTest, BasicShorthand) {
601 TestCascade cascade(GetDocument());
602 cascade.Add("margin", "1px 2px 3px 4px");
603 cascade.Apply();
604
605 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
606 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
607 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
608 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
609 }
610
TEST_F(StyleCascadeTest,BasicVarShorthand)611 TEST_F(StyleCascadeTest, BasicVarShorthand) {
612 TestCascade cascade(GetDocument());
613 cascade.Add("margin", "1px var(--x) 3px 4px");
614 cascade.Add("--x", "2px");
615 cascade.Apply();
616
617 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
618 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
619 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
620 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
621 }
622
TEST_F(StyleCascadeTest,ApplyingPendingSubstitutionFirst)623 TEST_F(StyleCascadeTest, ApplyingPendingSubstitutionFirst) {
624 TestCascade cascade(GetDocument());
625 cascade.Add("margin", "1px var(--x) 3px 4px");
626 cascade.Add("--x", "2px");
627 cascade.Add("margin-right", "5px");
628 cascade.Apply();
629
630 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
631 EXPECT_EQ("5px", cascade.ComputedValue("margin-right"));
632 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
633 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
634 }
635
TEST_F(StyleCascadeTest,ApplyingPendingSubstitutionLast)636 TEST_F(StyleCascadeTest, ApplyingPendingSubstitutionLast) {
637 TestCascade cascade(GetDocument());
638 cascade.Add("margin-right", "5px");
639 cascade.Add("margin", "1px var(--x) 3px 4px");
640 cascade.Add("--x", "2px");
641 cascade.Apply();
642
643 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
644 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
645 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
646 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
647 }
648
TEST_F(StyleCascadeTest,PendingSubstitutionInLogicalShorthand)649 TEST_F(StyleCascadeTest, PendingSubstitutionInLogicalShorthand) {
650 TestCascade cascade(GetDocument());
651 cascade.Add("margin-inline:var(--x)");
652 cascade.Add("--x:10px 20px");
653 cascade.Add("direction:rtl");
654 cascade.Apply();
655
656 EXPECT_EQ("20px", cascade.ComputedValue("margin-left"));
657 EXPECT_EQ("10px", cascade.ComputedValue("margin-right"));
658 }
659
TEST_F(StyleCascadeTest,DetectCycleByName)660 TEST_F(StyleCascadeTest, DetectCycleByName) {
661 TestCascade cascade(GetDocument());
662 TestCascadeResolver resolver;
663
664 // Two different CustomProperty instances with the same name:
665 CustomProperty a1("--a", GetDocument());
666 CustomProperty a2("--a", GetDocument());
667
668 {
669 TestCascadeAutoLock lock(a1, resolver);
670 EXPECT_FALSE(resolver.InCycle());
671
672 // This should still be detected as a cycle, even though it's not the same
673 // CustomProperty instance.
674 EXPECT_TRUE(resolver.DetectCycle(a2));
675 EXPECT_TRUE(resolver.InCycle());
676 }
677 EXPECT_FALSE(resolver.InCycle());
678 }
679
TEST_F(StyleCascadeTest,ResolverDetectCycle)680 TEST_F(StyleCascadeTest, ResolverDetectCycle) {
681 TestCascade cascade(GetDocument());
682 TestCascadeResolver resolver;
683
684 CustomProperty a("--a", GetDocument());
685 CustomProperty b("--b", GetDocument());
686 CustomProperty c("--c", GetDocument());
687
688 {
689 TestCascadeAutoLock lock(a, resolver);
690 EXPECT_FALSE(resolver.InCycle());
691 {
692 TestCascadeAutoLock lock(b, resolver);
693 EXPECT_FALSE(resolver.InCycle());
694 {
695 TestCascadeAutoLock lock(c, resolver);
696 EXPECT_FALSE(resolver.InCycle());
697
698 EXPECT_TRUE(resolver.DetectCycle(a));
699 EXPECT_TRUE(resolver.InCycle());
700 }
701 EXPECT_TRUE(resolver.InCycle());
702 }
703 EXPECT_TRUE(resolver.InCycle());
704 }
705 EXPECT_FALSE(resolver.InCycle());
706 }
707
TEST_F(StyleCascadeTest,ResolverDetectNoCycle)708 TEST_F(StyleCascadeTest, ResolverDetectNoCycle) {
709 TestCascade cascade(GetDocument());
710 TestCascadeResolver resolver;
711
712 CustomProperty a("--a", GetDocument());
713 CustomProperty b("--b", GetDocument());
714 CustomProperty c("--c", GetDocument());
715 CustomProperty x("--x", GetDocument());
716
717 {
718 TestCascadeAutoLock lock(a, resolver);
719 EXPECT_FALSE(resolver.InCycle());
720 {
721 TestCascadeAutoLock lock(b, resolver);
722 EXPECT_FALSE(resolver.InCycle());
723 {
724 TestCascadeAutoLock lock(c, resolver);
725 EXPECT_FALSE(resolver.InCycle());
726
727 EXPECT_FALSE(resolver.DetectCycle(x));
728 EXPECT_FALSE(resolver.InCycle());
729 }
730 EXPECT_FALSE(resolver.InCycle());
731 }
732 EXPECT_FALSE(resolver.InCycle());
733 }
734 EXPECT_FALSE(resolver.InCycle());
735 }
736
TEST_F(StyleCascadeTest,ResolverDetectCycleSelf)737 TEST_F(StyleCascadeTest, ResolverDetectCycleSelf) {
738 TestCascade cascade(GetDocument());
739 TestCascadeResolver resolver;
740
741 CustomProperty a("--a", GetDocument());
742
743 {
744 TestCascadeAutoLock lock(a, resolver);
745 EXPECT_FALSE(resolver.InCycle());
746
747 EXPECT_TRUE(resolver.DetectCycle(a));
748 EXPECT_TRUE(resolver.InCycle());
749 }
750 EXPECT_FALSE(resolver.InCycle());
751 }
752
TEST_F(StyleCascadeTest,ResolverDetectMultiCycle)753 TEST_F(StyleCascadeTest, ResolverDetectMultiCycle) {
754 using AutoLock = TestCascadeAutoLock;
755
756 TestCascade cascade(GetDocument());
757 TestCascadeResolver resolver;
758
759 CustomProperty a("--a", GetDocument());
760 CustomProperty b("--b", GetDocument());
761 CustomProperty c("--c", GetDocument());
762 CustomProperty d("--d", GetDocument());
763
764 {
765 AutoLock lock(a, resolver);
766 EXPECT_FALSE(resolver.InCycle());
767 {
768 AutoLock lock(b, resolver);
769 EXPECT_FALSE(resolver.InCycle());
770 {
771 AutoLock lock(c, resolver);
772 EXPECT_FALSE(resolver.InCycle());
773 {
774 AutoLock lock(d, resolver);
775 EXPECT_FALSE(resolver.InCycle());
776
777 // Cycle 1 (big cycle):
778 EXPECT_TRUE(resolver.DetectCycle(b));
779 EXPECT_TRUE(resolver.InCycle());
780 EXPECT_EQ(1u, resolver.CycleDepth());
781
782 // Cycle 2 (small cycle):
783 EXPECT_TRUE(resolver.DetectCycle(c));
784 EXPECT_TRUE(resolver.InCycle());
785 EXPECT_EQ(1u, resolver.CycleDepth());
786 }
787 }
788 EXPECT_TRUE(resolver.InCycle());
789 }
790 EXPECT_FALSE(resolver.InCycle());
791 }
792 EXPECT_FALSE(resolver.InCycle());
793 }
794
TEST_F(StyleCascadeTest,ResolverDetectMultiCycleReverse)795 TEST_F(StyleCascadeTest, ResolverDetectMultiCycleReverse) {
796 using AutoLock = TestCascadeAutoLock;
797
798 TestCascade cascade(GetDocument());
799 TestCascadeResolver resolver;
800
801 CustomProperty a("--a", GetDocument());
802 CustomProperty b("--b", GetDocument());
803 CustomProperty c("--c", GetDocument());
804 CustomProperty d("--d", GetDocument());
805
806 {
807 AutoLock lock(a, resolver);
808 EXPECT_FALSE(resolver.InCycle());
809 {
810 AutoLock lock(b, resolver);
811 EXPECT_FALSE(resolver.InCycle());
812 {
813 AutoLock lock(c, resolver);
814 EXPECT_FALSE(resolver.InCycle());
815 {
816 AutoLock lock(d, resolver);
817 EXPECT_FALSE(resolver.InCycle());
818
819 // Cycle 1 (small cycle):
820 EXPECT_TRUE(resolver.DetectCycle(c));
821 EXPECT_TRUE(resolver.InCycle());
822 EXPECT_EQ(2u, resolver.CycleDepth());
823
824 // Cycle 2 (big cycle):
825 EXPECT_TRUE(resolver.DetectCycle(b));
826 EXPECT_TRUE(resolver.InCycle());
827 EXPECT_EQ(1u, resolver.CycleDepth());
828 }
829 }
830 EXPECT_TRUE(resolver.InCycle());
831 }
832 EXPECT_FALSE(resolver.InCycle());
833 }
834 EXPECT_FALSE(resolver.InCycle());
835 }
836
TEST_F(StyleCascadeTest,ResolverMarkApplied)837 TEST_F(StyleCascadeTest, ResolverMarkApplied) {
838 TestCascadeResolver resolver(2);
839
840 CascadePriority priority(CascadeOrigin::kAuthor);
841 EXPECT_EQ(0, priority.GetGeneration());
842
843 resolver.MarkApplied(&priority);
844 EXPECT_EQ(2, priority.GetGeneration());
845
846 // Mark a second time to verify observation of the same generation.
847 resolver.MarkApplied(&priority);
848 EXPECT_EQ(2, priority.GetGeneration());
849 }
850
TEST_F(StyleCascadeTest,CurrentProperty)851 TEST_F(StyleCascadeTest, CurrentProperty) {
852 using AutoLock = TestCascadeAutoLock;
853
854 TestCascade cascade(GetDocument());
855 TestCascadeResolver resolver;
856
857 CustomProperty a("--a", GetDocument());
858 CustomProperty b("--b", GetDocument());
859 CustomProperty c("--c", GetDocument());
860
861 EXPECT_FALSE(resolver.CurrentProperty());
862 {
863 AutoLock lock(a, resolver);
864 EXPECT_EQ(&a, resolver.CurrentProperty());
865 {
866 AutoLock lock(b, resolver);
867 EXPECT_EQ(&b, resolver.CurrentProperty());
868 {
869 AutoLock lock(c, resolver);
870 EXPECT_EQ(&c, resolver.CurrentProperty());
871 }
872 EXPECT_EQ(&b, resolver.CurrentProperty());
873 }
874 EXPECT_EQ(&a, resolver.CurrentProperty());
875 }
876 EXPECT_FALSE(resolver.CurrentProperty());
877 }
878
TEST_F(StyleCascadeTest,ResolverMarkUnapplied)879 TEST_F(StyleCascadeTest, ResolverMarkUnapplied) {
880 TestCascadeResolver resolver(7);
881
882 CascadePriority priority(CascadeOrigin::kAuthor);
883 EXPECT_EQ(0, priority.GetGeneration());
884
885 resolver.MarkApplied(&priority);
886 EXPECT_EQ(7, priority.GetGeneration());
887
888 resolver.MarkUnapplied(&priority);
889 EXPECT_EQ(0, priority.GetGeneration());
890
891 // Mark a second time to verify observation of the same generation.
892 resolver.MarkUnapplied(&priority);
893 EXPECT_EQ(0, priority.GetGeneration());
894 }
895
TEST_F(StyleCascadeTest,BasicCycle)896 TEST_F(StyleCascadeTest, BasicCycle) {
897 TestCascade cascade(GetDocument());
898 cascade.Add("--a", "foo");
899 cascade.Add("--b", "bar");
900 cascade.Apply();
901
902 EXPECT_EQ("foo", cascade.ComputedValue("--a"));
903 EXPECT_EQ("bar", cascade.ComputedValue("--b"));
904
905 cascade.Reset();
906 cascade.Add("--a", "var(--b)");
907 cascade.Add("--b", "var(--a)");
908 cascade.Apply();
909
910 EXPECT_FALSE(cascade.ComputedValue("--a"));
911 EXPECT_FALSE(cascade.ComputedValue("--b"));
912 }
913
TEST_F(StyleCascadeTest,SelfCycle)914 TEST_F(StyleCascadeTest, SelfCycle) {
915 TestCascade cascade(GetDocument());
916 cascade.Add("--a", "foo");
917 cascade.Apply();
918
919 EXPECT_EQ("foo", cascade.ComputedValue("--a"));
920
921 cascade.Reset();
922 cascade.Add("--a", "var(--a)");
923 cascade.Apply();
924
925 EXPECT_FALSE(cascade.ComputedValue("--a"));
926 }
927
TEST_F(StyleCascadeTest,SelfCycleInFallback)928 TEST_F(StyleCascadeTest, SelfCycleInFallback) {
929 TestCascade cascade(GetDocument());
930 cascade.Add("--a", "var(--x, var(--a))");
931 cascade.Apply();
932
933 EXPECT_FALSE(cascade.ComputedValue("--a"));
934 }
935
TEST_F(StyleCascadeTest,SelfCycleInUnusedFallback)936 TEST_F(StyleCascadeTest, SelfCycleInUnusedFallback) {
937 TestCascade cascade(GetDocument());
938 cascade.Add("--a", "var(--b, var(--a))");
939 cascade.Add("--b", "10px");
940 cascade.Apply();
941
942 EXPECT_FALSE(cascade.ComputedValue("--a"));
943 EXPECT_EQ("10px", cascade.ComputedValue("--b"));
944 }
945
TEST_F(StyleCascadeTest,LongCycle)946 TEST_F(StyleCascadeTest, LongCycle) {
947 TestCascade cascade(GetDocument());
948 cascade.Add("--a", "var(--b)");
949 cascade.Add("--b", "var(--c)");
950 cascade.Add("--c", "var(--d)");
951 cascade.Add("--d", "var(--e)");
952 cascade.Add("--e", "var(--a)");
953 cascade.Apply();
954
955 EXPECT_FALSE(cascade.ComputedValue("--a"));
956 EXPECT_FALSE(cascade.ComputedValue("--b"));
957 EXPECT_FALSE(cascade.ComputedValue("--c"));
958 EXPECT_FALSE(cascade.ComputedValue("--d"));
959 EXPECT_FALSE(cascade.ComputedValue("--e"));
960 }
961
TEST_F(StyleCascadeTest,PartialCycle)962 TEST_F(StyleCascadeTest, PartialCycle) {
963 TestCascade cascade(GetDocument());
964 cascade.Add("--a", "var(--b)");
965 cascade.Add("--b", "var(--a)");
966 cascade.Add("--c", "bar var(--d) var(--a)");
967 cascade.Add("--d", "foo");
968 cascade.Apply();
969
970 EXPECT_FALSE(cascade.ComputedValue("--a"));
971 EXPECT_FALSE(cascade.ComputedValue("--b"));
972 EXPECT_FALSE(cascade.ComputedValue("--c"));
973 EXPECT_EQ("foo", cascade.ComputedValue("--d"));
974 }
975
TEST_F(StyleCascadeTest,VarCycleViaFallback)976 TEST_F(StyleCascadeTest, VarCycleViaFallback) {
977 TestCascade cascade(GetDocument());
978 cascade.Add("--a", "var(--b)");
979 cascade.Add("--b", "var(--x, var(--a))");
980 cascade.Add("--c", "var(--a)");
981 cascade.Apply();
982
983 EXPECT_FALSE(cascade.ComputedValue("--a"));
984 EXPECT_FALSE(cascade.ComputedValue("--b"));
985 EXPECT_FALSE(cascade.ComputedValue("--c"));
986 }
987
TEST_F(StyleCascadeTest,FallbackTriggeredByCycle)988 TEST_F(StyleCascadeTest, FallbackTriggeredByCycle) {
989 TestCascade cascade(GetDocument());
990 cascade.Add("--a", "var(--b)");
991 cascade.Add("--b", "var(--a)");
992 cascade.Add("--c", "var(--a,foo)");
993 cascade.Apply();
994
995 EXPECT_FALSE(cascade.ComputedValue("--a"));
996 EXPECT_FALSE(cascade.ComputedValue("--b"));
997 EXPECT_EQ("foo", cascade.ComputedValue("--c"));
998 }
999
TEST_F(StyleCascadeTest,RegisteredCycle)1000 TEST_F(StyleCascadeTest, RegisteredCycle) {
1001 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
1002 RegisterProperty(GetDocument(), "--b", "<length>", "0px", false);
1003
1004 TestCascade cascade(GetDocument());
1005 cascade.Add("--a", "var(--b)");
1006 cascade.Add("--b", "var(--a)");
1007 cascade.Apply();
1008
1009 EXPECT_FALSE(cascade.ComputedValue("--a"));
1010 EXPECT_FALSE(cascade.ComputedValue("--b"));
1011 }
1012
TEST_F(StyleCascadeTest,PartiallyRegisteredCycle)1013 TEST_F(StyleCascadeTest, PartiallyRegisteredCycle) {
1014 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
1015
1016 TestCascade cascade(GetDocument());
1017 cascade.Add("--a", "var(--b)");
1018 cascade.Add("--b", "var(--a)");
1019 cascade.Apply();
1020
1021 EXPECT_FALSE(cascade.ComputedValue("--a"));
1022 EXPECT_FALSE(cascade.ComputedValue("--b"));
1023 }
1024
TEST_F(StyleCascadeTest,FallbackTriggeredByRegisteredCycle)1025 TEST_F(StyleCascadeTest, FallbackTriggeredByRegisteredCycle) {
1026 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
1027 RegisterProperty(GetDocument(), "--b", "<length>", "0px", false);
1028
1029 TestCascade cascade(GetDocument());
1030 // Cycle:
1031 cascade.Add("--a", "var(--b)");
1032 cascade.Add("--b", "var(--a)");
1033 // References to cycle:
1034 cascade.Add("--c", "var(--a,1px)");
1035 cascade.Add("--d", "var(--b,2px)");
1036 cascade.Apply();
1037
1038 EXPECT_FALSE(cascade.ComputedValue("--a"));
1039 EXPECT_FALSE(cascade.ComputedValue("--b"));
1040 EXPECT_EQ("1px", cascade.ComputedValue("--c"));
1041 EXPECT_EQ("2px", cascade.ComputedValue("--d"));
1042 }
1043
TEST_F(StyleCascadeTest,CycleStillInvalidWithFallback)1044 TEST_F(StyleCascadeTest, CycleStillInvalidWithFallback) {
1045 TestCascade cascade(GetDocument());
1046 // Cycle:
1047 cascade.Add("--a", "var(--b,red)");
1048 cascade.Add("--b", "var(--a,red)");
1049 // References to cycle:
1050 cascade.Add("--c", "var(--a,green)");
1051 cascade.Add("--d", "var(--b,green)");
1052 cascade.Apply();
1053
1054 EXPECT_FALSE(cascade.ComputedValue("--a"));
1055 EXPECT_FALSE(cascade.ComputedValue("--b"));
1056 EXPECT_EQ("green", cascade.ComputedValue("--c"));
1057 EXPECT_EQ("green", cascade.ComputedValue("--d"));
1058 }
1059
TEST_F(StyleCascadeTest,CycleInFallbackStillInvalid)1060 TEST_F(StyleCascadeTest, CycleInFallbackStillInvalid) {
1061 TestCascade cascade(GetDocument());
1062 // Cycle:
1063 cascade.Add("--a", "var(--b,red)");
1064 cascade.Add("--b", "var(--x,var(--a))");
1065 // References to cycle:
1066 cascade.Add("--c", "var(--a,green)");
1067 cascade.Add("--d", "var(--b,green)");
1068 cascade.Apply();
1069
1070 EXPECT_FALSE(cascade.ComputedValue("--a"));
1071 EXPECT_FALSE(cascade.ComputedValue("--b"));
1072 EXPECT_EQ("green", cascade.ComputedValue("--c"));
1073 EXPECT_EQ("green", cascade.ComputedValue("--d"));
1074 }
1075
TEST_F(StyleCascadeTest,CycleMultiple)1076 TEST_F(StyleCascadeTest, CycleMultiple) {
1077 TestCascade cascade(GetDocument());
1078 // Cycle:
1079 cascade.Add("--a", "var(--c, red)");
1080 cascade.Add("--b", "var(--c, red)");
1081 cascade.Add("--c", "var(--a, blue) var(--b, blue)");
1082 // References to cycle:
1083 cascade.Add("--d", "var(--a,green)");
1084 cascade.Add("--e", "var(--b,green)");
1085 cascade.Add("--f", "var(--c,green)");
1086 cascade.Apply();
1087
1088 EXPECT_FALSE(cascade.ComputedValue("--a"));
1089 EXPECT_FALSE(cascade.ComputedValue("--b"));
1090 EXPECT_FALSE(cascade.ComputedValue("--c"));
1091 EXPECT_EQ("green", cascade.ComputedValue("--d"));
1092 EXPECT_EQ("green", cascade.ComputedValue("--e"));
1093 EXPECT_EQ("green", cascade.ComputedValue("--f"));
1094 }
1095
TEST_F(StyleCascadeTest,CycleMultipleFallback)1096 TEST_F(StyleCascadeTest, CycleMultipleFallback) {
1097 TestCascade cascade(GetDocument());
1098 // Cycle:
1099 cascade.Add("--a", "var(--b, red)");
1100 cascade.Add("--b", "var(--a, var(--c, red))");
1101 cascade.Add("--c", "var(--b, red)");
1102 // References to cycle:
1103 cascade.Add("--d", "var(--a,green)");
1104 cascade.Add("--e", "var(--b,green)");
1105 cascade.Add("--f", "var(--c,green)");
1106 cascade.Apply();
1107
1108 EXPECT_FALSE(cascade.ComputedValue("--a"));
1109 EXPECT_FALSE(cascade.ComputedValue("--b"));
1110 EXPECT_FALSE(cascade.ComputedValue("--c"));
1111 EXPECT_EQ("green", cascade.ComputedValue("--d"));
1112 EXPECT_EQ("green", cascade.ComputedValue("--e"));
1113 EXPECT_EQ("green", cascade.ComputedValue("--f"));
1114 }
1115
TEST_F(StyleCascadeTest,CycleMultipleUnusedFallback)1116 TEST_F(StyleCascadeTest, CycleMultipleUnusedFallback) {
1117 TestCascade cascade(GetDocument());
1118 cascade.Add("--a", "red");
1119 // Cycle:
1120 cascade.Add("--b", "var(--c, red)");
1121 cascade.Add("--c", "var(--a, var(--b, red) var(--d, red))");
1122 cascade.Add("--d", "var(--c, red)");
1123 // References to cycle:
1124 cascade.Add("--e", "var(--b,green)");
1125 cascade.Add("--f", "var(--c,green)");
1126 cascade.Add("--g", "var(--d,green)");
1127 cascade.Apply();
1128
1129 EXPECT_FALSE(cascade.ComputedValue("--b"));
1130 EXPECT_FALSE(cascade.ComputedValue("--c"));
1131 EXPECT_FALSE(cascade.ComputedValue("--d"));
1132 EXPECT_EQ("green", cascade.ComputedValue("--e"));
1133 EXPECT_EQ("green", cascade.ComputedValue("--f"));
1134 EXPECT_EQ("green", cascade.ComputedValue("--g"));
1135 }
1136
TEST_F(StyleCascadeTest,CycleReferencedFromStandardProperty)1137 TEST_F(StyleCascadeTest, CycleReferencedFromStandardProperty) {
1138 TestCascade cascade(GetDocument());
1139 cascade.Add("--a", "var(--b)");
1140 cascade.Add("--b", "var(--a)");
1141 cascade.Add("color:var(--a,green)");
1142 cascade.Apply();
1143
1144 EXPECT_FALSE(cascade.ComputedValue("--a"));
1145 EXPECT_FALSE(cascade.ComputedValue("--b"));
1146 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
1147 }
1148
TEST_F(StyleCascadeTest,CycleReferencedFromShorthand)1149 TEST_F(StyleCascadeTest, CycleReferencedFromShorthand) {
1150 TestCascade cascade(GetDocument());
1151 cascade.Add("--a", "var(--b)");
1152 cascade.Add("--b", "var(--a)");
1153 cascade.Add("background", "var(--a,green)");
1154 cascade.Apply();
1155
1156 EXPECT_FALSE(cascade.ComputedValue("--a"));
1157 EXPECT_FALSE(cascade.ComputedValue("--b"));
1158 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("background-color"));
1159 }
1160
TEST_F(StyleCascadeTest,EmUnit)1161 TEST_F(StyleCascadeTest, EmUnit) {
1162 TestCascade cascade(GetDocument());
1163 cascade.Add("font-size", "10px");
1164 cascade.Add("width", "10em");
1165 cascade.Apply();
1166
1167 EXPECT_EQ("100px", cascade.ComputedValue("width"));
1168 }
1169
TEST_F(StyleCascadeTest,EmUnitCustomProperty)1170 TEST_F(StyleCascadeTest, EmUnitCustomProperty) {
1171 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1172
1173 TestCascade cascade(GetDocument());
1174 cascade.Add("font-size", "10px");
1175 cascade.Add("--x", "10em");
1176 cascade.Apply();
1177
1178 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1179 }
1180
TEST_F(StyleCascadeTest,EmUnitNonCycle)1181 TEST_F(StyleCascadeTest, EmUnitNonCycle) {
1182 TestCascade parent(GetDocument());
1183 parent.Add("font-size", "10px");
1184 parent.Apply();
1185
1186 TestCascade cascade(GetDocument());
1187 cascade.InheritFrom(parent.TakeStyle());
1188 cascade.Add("font-size", "var(--x)");
1189 cascade.Add("--x", "10em");
1190 cascade.Apply();
1191
1192 // Note: Only registered properties can have cycles with font-size.
1193 EXPECT_EQ("100px", cascade.ComputedValue("font-size"));
1194 }
1195
TEST_F(StyleCascadeTest,EmUnitCycle)1196 TEST_F(StyleCascadeTest, EmUnitCycle) {
1197 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1198
1199 TestCascade cascade(GetDocument());
1200 cascade.Add("font-size", "var(--x)");
1201 cascade.Add("--x", "10em");
1202 cascade.Apply();
1203
1204 EXPECT_FALSE(cascade.ComputedValue("--x"));
1205 }
1206
TEST_F(StyleCascadeTest,SubstitutingEmCycles)1207 TEST_F(StyleCascadeTest, SubstitutingEmCycles) {
1208 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1209
1210 TestCascade cascade(GetDocument());
1211 cascade.Add("font-size", "var(--x)");
1212 cascade.Add("--x", "10em");
1213 cascade.Add("--y", "var(--x)");
1214 cascade.Add("--z", "var(--x,1px)");
1215 cascade.Apply();
1216
1217 EXPECT_FALSE(cascade.ComputedValue("--y"));
1218 EXPECT_EQ("1px", cascade.ComputedValue("--z"));
1219 }
1220
TEST_F(StyleCascadeTest,RemUnit)1221 TEST_F(StyleCascadeTest, RemUnit) {
1222 SetRootFont("10px");
1223 UpdateAllLifecyclePhasesForTest();
1224
1225 TestCascade cascade(GetDocument());
1226 cascade.Add("width", "10rem");
1227 cascade.Apply();
1228
1229 EXPECT_EQ("100px", cascade.ComputedValue("width"));
1230 }
1231
TEST_F(StyleCascadeTest,RemUnitCustomProperty)1232 TEST_F(StyleCascadeTest, RemUnitCustomProperty) {
1233 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1234
1235 SetRootFont("10px");
1236 UpdateAllLifecyclePhasesForTest();
1237
1238 TestCascade cascade(GetDocument());
1239 cascade.Add("--x", "10rem");
1240 cascade.Apply();
1241
1242 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1243 }
1244
TEST_F(StyleCascadeTest,RemUnitInFontSize)1245 TEST_F(StyleCascadeTest, RemUnitInFontSize) {
1246 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1247
1248 SetRootFont("10px");
1249 UpdateAllLifecyclePhasesForTest();
1250
1251 TestCascade cascade(GetDocument());
1252 cascade.Add("font-size", "1rem");
1253 cascade.Add("--x", "10rem");
1254 cascade.Apply();
1255
1256 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1257 }
1258
TEST_F(StyleCascadeTest,RemUnitInRootFontSizeCycle)1259 TEST_F(StyleCascadeTest, RemUnitInRootFontSizeCycle) {
1260 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1261
1262 TestCascade cascade(GetDocument(), DocumentElement());
1263 cascade.Add("font-size", "var(--x)");
1264 cascade.Add("--x", "1rem");
1265 cascade.Apply();
1266
1267 EXPECT_FALSE(cascade.ComputedValue("--x"));
1268 }
1269
TEST_F(StyleCascadeTest,RemUnitInRootFontSizeNonCycle)1270 TEST_F(StyleCascadeTest, RemUnitInRootFontSizeNonCycle) {
1271 TestCascade cascade(GetDocument(), DocumentElement());
1272 cascade.Add("font-size", "initial");
1273 cascade.Apply();
1274
1275 String expected = cascade.ComputedValue("font-size");
1276
1277 cascade.Reset();
1278 cascade.Add("font-size", "var(--x)");
1279 cascade.Add("--x", "1rem");
1280 cascade.Apply();
1281
1282 // Note: Only registered properties can have cycles with font-size.
1283 EXPECT_EQ("1rem", cascade.ComputedValue("--x"));
1284 EXPECT_EQ(expected, cascade.ComputedValue("font-size"));
1285 }
1286
TEST_F(StyleCascadeTest,Initial)1287 TEST_F(StyleCascadeTest, Initial) {
1288 TestCascade parent(GetDocument());
1289 parent.Add("--x", "foo");
1290 parent.Apply();
1291
1292 TestCascade cascade(GetDocument());
1293 cascade.InheritFrom(parent.TakeStyle());
1294 cascade.Add("--y", "foo");
1295 cascade.Apply();
1296
1297 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1298 EXPECT_EQ("foo", cascade.ComputedValue("--y"));
1299
1300 cascade.Reset();
1301 cascade.Add("--x", "initial");
1302 cascade.Add("--y", "initial");
1303 cascade.Apply();
1304
1305 EXPECT_FALSE(cascade.ComputedValue("--x"));
1306 EXPECT_FALSE(cascade.ComputedValue("--y"));
1307 }
1308
TEST_F(StyleCascadeTest,Inherit)1309 TEST_F(StyleCascadeTest, Inherit) {
1310 TestCascade parent(GetDocument());
1311 parent.Add("--x", "foo");
1312 parent.Apply();
1313
1314 TestCascade cascade(GetDocument());
1315 cascade.InheritFrom(parent.TakeStyle());
1316
1317 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1318
1319 cascade.Add("--x", "bar");
1320 cascade.Apply();
1321 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1322
1323 cascade.Reset();
1324 cascade.Add("--x", "inherit");
1325 cascade.Apply();
1326 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1327 }
1328
TEST_F(StyleCascadeTest,Unset)1329 TEST_F(StyleCascadeTest, Unset) {
1330 TestCascade parent(GetDocument());
1331 parent.Add("--x", "foo");
1332 parent.Apply();
1333
1334 TestCascade cascade(GetDocument());
1335 cascade.InheritFrom(parent.TakeStyle());
1336 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1337
1338 cascade.Add("--x", "bar");
1339 cascade.Apply();
1340 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1341
1342 cascade.Reset();
1343 cascade.Add("--x", "unset");
1344 cascade.Apply();
1345 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1346 }
1347
TEST_F(StyleCascadeTest,RevertUA)1348 TEST_F(StyleCascadeTest, RevertUA) {
1349 TestCascade cascade(GetDocument());
1350 cascade.Add("display:block", CascadeOrigin::kUserAgent);
1351 cascade.Add("display:revert", CascadeOrigin::kUserAgent);
1352
1353 cascade.Add("display:block", CascadeOrigin::kUser);
1354 cascade.Add("display:revert", CascadeOrigin::kUser);
1355
1356 cascade.Add("display:block", CascadeOrigin::kAuthor);
1357 cascade.Add("display:revert", CascadeOrigin::kAuthor);
1358
1359 cascade.Apply();
1360
1361 EXPECT_EQ("inline", cascade.ComputedValue("display"));
1362 }
1363
TEST_F(StyleCascadeTest,RevertStandardProperty)1364 TEST_F(StyleCascadeTest, RevertStandardProperty) {
1365 TestCascade cascade(GetDocument());
1366 cascade.Add("left:10px", CascadeOrigin::kUserAgent);
1367 cascade.Add("right:10px", CascadeOrigin::kUserAgent);
1368
1369 cascade.Add("right:20px", CascadeOrigin::kUser);
1370 cascade.Add("right:revert", CascadeOrigin::kUser);
1371 cascade.Add("top:20px", CascadeOrigin::kUser);
1372 cascade.Add("bottom:20px", CascadeOrigin::kUser);
1373
1374 cascade.Add("bottom:30px", CascadeOrigin::kAuthor);
1375 cascade.Add("bottom:revert", CascadeOrigin::kAuthor);
1376 cascade.Add("left:30px", CascadeOrigin::kAuthor);
1377 cascade.Add("left:revert", CascadeOrigin::kAuthor);
1378 cascade.Add("right:revert", CascadeOrigin::kAuthor);
1379 cascade.Apply();
1380
1381 EXPECT_EQ("20px", cascade.ComputedValue("top"));
1382 EXPECT_EQ("10px", cascade.ComputedValue("right"));
1383 EXPECT_EQ("20px", cascade.ComputedValue("bottom"));
1384 EXPECT_EQ("10px", cascade.ComputedValue("left"));
1385 }
1386
TEST_F(StyleCascadeTest,RevertCustomProperty)1387 TEST_F(StyleCascadeTest, RevertCustomProperty) {
1388 TestCascade cascade(GetDocument());
1389 cascade.Add("--x:10px", CascadeOrigin::kUser);
1390
1391 cascade.Add("--y:fail", CascadeOrigin::kAuthor);
1392
1393 cascade.Add("--x:revert", CascadeOrigin::kAuthor);
1394 cascade.Add("--y:revert", CascadeOrigin::kAuthor);
1395
1396 cascade.Apply();
1397
1398 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
1399 EXPECT_FALSE(cascade.ComputedValue("--y"));
1400 }
1401
TEST_F(StyleCascadeTest,RevertChain)1402 TEST_F(StyleCascadeTest, RevertChain) {
1403 TestCascade cascade(GetDocument());
1404 cascade.Add("width:10px", CascadeOrigin::kUserAgent);
1405
1406 cascade.Add("width:revert", CascadeOrigin::kUser);
1407 cascade.Add("--x:revert", CascadeOrigin::kUser);
1408
1409 cascade.Add("width:revert", CascadeOrigin::kAuthor);
1410 cascade.Add("--x:revert", CascadeOrigin::kAuthor);
1411 cascade.Apply();
1412
1413 EXPECT_EQ("10px", cascade.ComputedValue("width"));
1414 EXPECT_FALSE(cascade.ComputedValue("--x"));
1415 }
1416
TEST_F(StyleCascadeTest,RevertFromAuthorToUA)1417 TEST_F(StyleCascadeTest, RevertFromAuthorToUA) {
1418 TestCascade cascade(GetDocument());
1419 cascade.Add("width:10px", CascadeOrigin::kUserAgent);
1420 cascade.Add("height:10px", CascadeOrigin::kUserAgent);
1421
1422 cascade.Add("width:20px", CascadeOrigin::kAuthor);
1423 cascade.Add("height:20px", CascadeOrigin::kAuthor);
1424 cascade.Add("width:revert", CascadeOrigin::kAuthor);
1425 cascade.Add("height:revert", CascadeOrigin::kAuthor);
1426 cascade.Apply();
1427
1428 EXPECT_EQ("10px", cascade.ComputedValue("width"));
1429 EXPECT_EQ("10px", cascade.ComputedValue("height"));
1430 }
1431
TEST_F(StyleCascadeTest,RevertInitialFallback)1432 TEST_F(StyleCascadeTest, RevertInitialFallback) {
1433 TestCascade cascade(GetDocument());
1434 cascade.Add("width:20px", CascadeOrigin::kAuthor);
1435 cascade.Add("width:revert", CascadeOrigin::kAuthor);
1436 cascade.Apply();
1437
1438 EXPECT_EQ("auto", cascade.ComputedValue("width"));
1439 }
1440
TEST_F(StyleCascadeTest,RevertInheritedFallback)1441 TEST_F(StyleCascadeTest, RevertInheritedFallback) {
1442 TestCascade parent(GetDocument());
1443 parent.Add("color", "red");
1444 parent.Apply();
1445
1446 TestCascade cascade(GetDocument());
1447 cascade.InheritFrom(parent.TakeStyle());
1448 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("color"));
1449
1450 cascade.Add("color:black", CascadeOrigin::kAuthor);
1451 cascade.Add("color:revert", CascadeOrigin::kAuthor);
1452 cascade.Apply();
1453 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("color"));
1454 }
1455
TEST_F(StyleCascadeTest,RevertRegistered)1456 TEST_F(StyleCascadeTest, RevertRegistered) {
1457 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1458
1459 TestCascade cascade(GetDocument());
1460 cascade.Add("--x:20px", CascadeOrigin::kUser);
1461 cascade.Add("--x:100px", CascadeOrigin::kAuthor);
1462 cascade.Add("--x:revert", CascadeOrigin::kAuthor);
1463 cascade.Apply();
1464
1465 EXPECT_EQ("20px", cascade.ComputedValue("--x"));
1466 }
1467
TEST_F(StyleCascadeTest,RevertRegisteredInitialFallback)1468 TEST_F(StyleCascadeTest, RevertRegisteredInitialFallback) {
1469 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1470
1471 TestCascade cascade(GetDocument());
1472 cascade.Add("--x:20px", CascadeOrigin::kAuthor);
1473 cascade.Add("--x:revert", CascadeOrigin::kAuthor);
1474 cascade.Apply();
1475
1476 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1477 }
1478
TEST_F(StyleCascadeTest,RevertRegisteredInheritedFallback)1479 TEST_F(StyleCascadeTest, RevertRegisteredInheritedFallback) {
1480 RegisterProperty(GetDocument(), "--x", "<length>", "0px", true);
1481
1482 TestCascade parent(GetDocument());
1483 parent.Add("--x", "1px");
1484 parent.Apply();
1485
1486 TestCascade cascade(GetDocument());
1487 cascade.InheritFrom(parent.TakeStyle());
1488 EXPECT_EQ("1px", cascade.ComputedValue("--x"));
1489
1490 cascade.Add("--x:100px", CascadeOrigin::kAuthor);
1491 cascade.Add("--x:revert", CascadeOrigin::kAuthor);
1492 cascade.Apply();
1493 EXPECT_EQ("1px", cascade.ComputedValue("--x"));
1494 }
1495
TEST_F(StyleCascadeTest,RevertUASurrogate)1496 TEST_F(StyleCascadeTest, RevertUASurrogate) {
1497 TestCascade cascade(GetDocument());
1498
1499 // User-agent:
1500
1501 // Only logical:
1502 cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
1503 cascade.Add("min-inline-size:11px", CascadeOrigin::kUserAgent);
1504 // Only physical:
1505 cascade.Add("height:12px", CascadeOrigin::kUserAgent);
1506 cascade.Add("min-height:13px", CascadeOrigin::kUserAgent);
1507 // Physical first:
1508 cascade.Add("margin-left:14px", CascadeOrigin::kUserAgent);
1509 cascade.Add("padding-left:15px", CascadeOrigin::kUserAgent);
1510 cascade.Add("margin-inline-start:16px", CascadeOrigin::kUserAgent);
1511 cascade.Add("padding-inline-start:17px", CascadeOrigin::kUserAgent);
1512 // Logical first:
1513 cascade.Add("margin-inline-end:18px", CascadeOrigin::kUserAgent);
1514 cascade.Add("padding-inline-end:19px", CascadeOrigin::kUserAgent);
1515 cascade.Add("margin-right:20px", CascadeOrigin::kUserAgent);
1516 cascade.Add("padding-right:21px", CascadeOrigin::kUserAgent);
1517
1518 // Author:
1519
1520 cascade.Add("width:100px", CascadeOrigin::kAuthor);
1521 cascade.Add("height:101px", CascadeOrigin::kAuthor);
1522 cascade.Add("margin:102px", CascadeOrigin::kAuthor);
1523 cascade.Add("padding:103px", CascadeOrigin::kAuthor);
1524 cascade.Add("min-width:104px", CascadeOrigin::kAuthor);
1525 cascade.Add("min-height:105px", CascadeOrigin::kAuthor);
1526 // Revert via physical:
1527 cascade.Add("width:revert", CascadeOrigin::kAuthor);
1528 cascade.Add("height:revert", CascadeOrigin::kAuthor);
1529 cascade.Add("margin-left:revert", CascadeOrigin::kAuthor);
1530 cascade.Add("margin-right:revert", CascadeOrigin::kAuthor);
1531 // Revert via logical:
1532 cascade.Add("min-inline-size:revert", CascadeOrigin::kAuthor);
1533 cascade.Add("min-block-size:revert", CascadeOrigin::kAuthor);
1534 cascade.Add("padding-inline-start:revert", CascadeOrigin::kAuthor);
1535 cascade.Add("padding-inline-end:revert", CascadeOrigin::kAuthor);
1536
1537 cascade.Apply();
1538
1539 EXPECT_EQ("10px", cascade.ComputedValue("width"));
1540 EXPECT_EQ("12px", cascade.ComputedValue("height"));
1541 EXPECT_EQ("11px", cascade.ComputedValue("min-width"));
1542 EXPECT_EQ("13px", cascade.ComputedValue("min-height"));
1543 EXPECT_EQ("102px", cascade.ComputedValue("margin-top"));
1544 EXPECT_EQ("20px", cascade.ComputedValue("margin-right"));
1545 EXPECT_EQ("102px", cascade.ComputedValue("margin-bottom"));
1546 EXPECT_EQ("16px", cascade.ComputedValue("margin-left"));
1547 EXPECT_EQ("103px", cascade.ComputedValue("padding-top"));
1548 EXPECT_EQ("21px", cascade.ComputedValue("padding-right"));
1549 EXPECT_EQ("103px", cascade.ComputedValue("padding-bottom"));
1550 EXPECT_EQ("17px", cascade.ComputedValue("padding-left"));
1551
1552 EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
1553 EXPECT_EQ("12px", cascade.ComputedValue("block-size"));
1554 EXPECT_EQ("11px", cascade.ComputedValue("min-inline-size"));
1555 EXPECT_EQ("13px", cascade.ComputedValue("min-block-size"));
1556 EXPECT_EQ("102px", cascade.ComputedValue("margin-block-start"));
1557 EXPECT_EQ("20px", cascade.ComputedValue("margin-inline-end"));
1558 EXPECT_EQ("102px", cascade.ComputedValue("margin-block-end"));
1559 EXPECT_EQ("16px", cascade.ComputedValue("margin-inline-start"));
1560 EXPECT_EQ("103px", cascade.ComputedValue("padding-block-start"));
1561 EXPECT_EQ("21px", cascade.ComputedValue("padding-inline-end"));
1562 EXPECT_EQ("103px", cascade.ComputedValue("padding-block-end"));
1563 EXPECT_EQ("17px", cascade.ComputedValue("padding-inline-start"));
1564 }
1565
TEST_F(StyleCascadeTest,RevertWithImportantPhysical)1566 TEST_F(StyleCascadeTest, RevertWithImportantPhysical) {
1567 TestCascade cascade(GetDocument());
1568 cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
1569 cascade.Add("block-size:11px", CascadeOrigin::kUserAgent);
1570
1571 cascade.Add("width:100px", CascadeOrigin::kAuthor);
1572 cascade.Add("height:101px", CascadeOrigin::kAuthor);
1573 cascade.Add("width:revert !important", CascadeOrigin::kAuthor);
1574 cascade.Add("inline-size:101px", CascadeOrigin::kAuthor);
1575 cascade.Add("block-size:102px", CascadeOrigin::kAuthor);
1576 cascade.Add("height:revert !important", CascadeOrigin::kAuthor);
1577 cascade.Apply();
1578
1579 EXPECT_EQ("10px", cascade.ComputedValue("width"));
1580 EXPECT_EQ("11px", cascade.ComputedValue("height"));
1581 EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
1582 EXPECT_EQ("11px", cascade.ComputedValue("block-size"));
1583 }
1584
TEST_F(StyleCascadeTest,RevertWithImportantLogical)1585 TEST_F(StyleCascadeTest, RevertWithImportantLogical) {
1586 TestCascade cascade(GetDocument());
1587 cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
1588 cascade.Add("block-size:11px", CascadeOrigin::kUserAgent);
1589
1590 cascade.Add("inline-size:revert !important", CascadeOrigin::kAuthor);
1591 cascade.Add("width:100px", CascadeOrigin::kAuthor);
1592 cascade.Add("height:101px", CascadeOrigin::kAuthor);
1593 cascade.Add("block-size:revert !important", CascadeOrigin::kAuthor);
1594 cascade.Apply();
1595
1596 EXPECT_EQ("10px", cascade.ComputedValue("width"));
1597 EXPECT_EQ("11px", cascade.ComputedValue("height"));
1598 EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
1599 EXPECT_EQ("11px", cascade.ComputedValue("block-size"));
1600 }
1601
TEST_F(StyleCascadeTest,RevertSurrogateChain)1602 TEST_F(StyleCascadeTest, RevertSurrogateChain) {
1603 TestCascade cascade(GetDocument());
1604
1605 cascade.Add("inline-size:revert", CascadeOrigin::kUserAgent);
1606 cascade.Add("block-size:10px", CascadeOrigin::kUserAgent);
1607 cascade.Add("min-inline-size:11px", CascadeOrigin::kUserAgent);
1608 cascade.Add("min-block-size:12px", CascadeOrigin::kUserAgent);
1609 cascade.Add("margin-inline:13px", CascadeOrigin::kUserAgent);
1610 cascade.Add("margin-block:14px", CascadeOrigin::kUserAgent);
1611 cascade.Add("margin-top:revert", CascadeOrigin::kUserAgent);
1612 cascade.Add("margin-left:15px", CascadeOrigin::kUserAgent);
1613 cascade.Add("margin-bottom:16px", CascadeOrigin::kUserAgent);
1614 cascade.Add("margin-block-end:17px", CascadeOrigin::kUserAgent);
1615
1616 cascade.Add("inline-size:101px", CascadeOrigin::kUser);
1617 cascade.Add("block-size:102px", CascadeOrigin::kUser);
1618 cascade.Add("width:revert", CascadeOrigin::kUser);
1619 cascade.Add("height:revert", CascadeOrigin::kUser);
1620 cascade.Add("min-inline-size:103px", CascadeOrigin::kUser);
1621 cascade.Add("min-block-size:104px", CascadeOrigin::kUser);
1622 cascade.Add("margin:105px", CascadeOrigin::kUser);
1623 cascade.Add("margin-block-start:revert", CascadeOrigin::kUser);
1624 cascade.Add("margin-inline-start:106px", CascadeOrigin::kUser);
1625 cascade.Add("margin-block-end:revert", CascadeOrigin::kUser);
1626 cascade.Add("margin-right:107px", CascadeOrigin::kUser);
1627
1628 cascade.Add("inline-size:revert", CascadeOrigin::kAuthor);
1629 cascade.Add("block-size:revert", CascadeOrigin::kAuthor);
1630 cascade.Add("min-inline-size:revert", CascadeOrigin::kAuthor);
1631 cascade.Add("min-block-size:1001px", CascadeOrigin::kAuthor);
1632 cascade.Add("margin:1002px", CascadeOrigin::kAuthor);
1633 cascade.Add("margin-top:revert", CascadeOrigin::kAuthor);
1634 cascade.Add("margin-left:1003px", CascadeOrigin::kAuthor);
1635 cascade.Add("margin-bottom:1004px", CascadeOrigin::kAuthor);
1636 cascade.Add("margin-right:1005px", CascadeOrigin::kAuthor);
1637 cascade.Apply();
1638
1639 EXPECT_EQ("auto", cascade.ComputedValue("width"));
1640 EXPECT_EQ("10px", cascade.ComputedValue("height"));
1641 EXPECT_EQ("103px", cascade.ComputedValue("min-width"));
1642 EXPECT_EQ("1001px", cascade.ComputedValue("min-height"));
1643 EXPECT_EQ("0px", cascade.ComputedValue("margin-top"));
1644 EXPECT_EQ("1005px", cascade.ComputedValue("margin-right"));
1645 EXPECT_EQ("1004px", cascade.ComputedValue("margin-bottom"));
1646 EXPECT_EQ("1003px", cascade.ComputedValue("margin-left"));
1647 }
1648
TEST_F(StyleCascadeTest,RevertInKeyframe)1649 TEST_F(StyleCascadeTest, RevertInKeyframe) {
1650 AppendSheet(R"HTML(
1651 @keyframes test {
1652 from { margin-left: 0px; }
1653 to { margin-left: revert; }
1654 }
1655 )HTML");
1656
1657 TestCascade cascade(GetDocument());
1658
1659 cascade.Add("margin-left:100px", CascadeOrigin::kUserAgent);
1660 cascade.Add("animation:test linear 1000s -500s");
1661 cascade.Apply();
1662
1663 cascade.CalculateAnimationUpdate();
1664 cascade.Apply();
1665
1666 EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
1667 }
1668
TEST_F(StyleCascadeTest,RevertToCustomPropertyInKeyframe)1669 TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframe) {
1670 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1671
1672 AppendSheet(R"HTML(
1673 @keyframes test {
1674 from { --x: 0px; }
1675 to { --x: revert; }
1676 }
1677 )HTML");
1678
1679 TestCascade cascade(GetDocument());
1680
1681 cascade.Add("--x:100px", CascadeOrigin::kUser);
1682 cascade.Add("--x:1000px", CascadeOrigin::kAuthor);
1683 cascade.Add("animation:test linear 1000s -500s");
1684 cascade.Apply();
1685
1686 cascade.CalculateAnimationUpdate();
1687 cascade.Apply();
1688
1689 EXPECT_EQ("50px", cascade.ComputedValue("--x"));
1690 }
1691
TEST_F(StyleCascadeTest,RevertToCustomPropertyInKeyframeUnset)1692 TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeUnset) {
1693 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1694 RegisterProperty(GetDocument(), "--y", "<length>", "1000px", true);
1695
1696 AppendSheet(R"HTML(
1697 @keyframes test {
1698 from { --x: 100px; --y: 100px; }
1699 to { --x: revert; --y: revert; }
1700 }
1701 )HTML");
1702
1703 TestCascade parent(GetDocument());
1704 parent.Add("--y: 0px");
1705 parent.Apply();
1706 EXPECT_EQ("0px", parent.ComputedValue("--y"));
1707
1708 TestCascade cascade(GetDocument());
1709 cascade.InheritFrom(parent.TakeStyle());
1710 cascade.Add("--x:10000px", CascadeOrigin::kAuthor);
1711 cascade.Add("--y:10000px", CascadeOrigin::kAuthor);
1712 cascade.Add("animation:test linear 1000s -500s");
1713 cascade.Apply();
1714
1715 cascade.CalculateAnimationUpdate();
1716 cascade.Apply();
1717
1718 EXPECT_EQ("50px", cascade.ComputedValue("--x"));
1719 EXPECT_EQ("50px", cascade.ComputedValue("--y"));
1720 }
1721
TEST_F(StyleCascadeTest,RevertToCustomPropertyInKeyframeEmptyInherit)1722 TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeEmptyInherit) {
1723 RegisterProperty(GetDocument(), "--x", "<length>", "0px", true);
1724
1725 AppendSheet(R"HTML(
1726 @keyframes test {
1727 from { --x: 100px; }
1728 to { --x: revert; }
1729 }
1730 )HTML");
1731
1732 TestCascade cascade(GetDocument());
1733 cascade.Add("--x:10000px", CascadeOrigin::kAuthor);
1734 cascade.Add("animation:test linear 1000s -500s");
1735 cascade.Apply();
1736
1737 cascade.CalculateAnimationUpdate();
1738 cascade.Apply();
1739
1740 EXPECT_EQ("50px", cascade.ComputedValue("--x"));
1741 }
1742
TEST_F(StyleCascadeTest,RevertInKeyframeResponsive)1743 TEST_F(StyleCascadeTest, RevertInKeyframeResponsive) {
1744 AppendSheet(R"HTML(
1745 @keyframes test {
1746 from { margin-left: 0px; }
1747 to { margin-left: revert; }
1748 }
1749 )HTML");
1750
1751 TestCascade cascade(GetDocument());
1752
1753 cascade.Add("--x:100px", CascadeOrigin::kUser);
1754 cascade.Add("margin-left:var(--x)", CascadeOrigin::kUser);
1755 cascade.Add("animation:test linear 1000s -500s");
1756 cascade.Apply();
1757 cascade.CalculateAnimationUpdate();
1758 cascade.Apply();
1759
1760 EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
1761
1762 cascade.Reset();
1763 cascade.Add("--x:100px", CascadeOrigin::kUser);
1764 cascade.Add("margin-left:var(--x)", CascadeOrigin::kUser);
1765 cascade.Add("animation:test linear 1000s -500s");
1766 cascade.Add("--x:80px", CascadeOrigin::kAuthor);
1767 cascade.Apply();
1768 cascade.CalculateAnimationUpdate();
1769 cascade.Apply();
1770
1771 EXPECT_EQ("40px", cascade.ComputedValue("margin-left"));
1772 }
1773
TEST_F(StyleCascadeTest,RevertToCycleInKeyframe)1774 TEST_F(StyleCascadeTest, RevertToCycleInKeyframe) {
1775 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1776
1777 AppendSheet(R"HTML(
1778 @keyframes test {
1779 from { --x: 100px; }
1780 to { --x: revert; }
1781 }
1782 )HTML");
1783
1784 TestCascade cascade(GetDocument());
1785
1786 cascade.Add("--x:var(--y)", CascadeOrigin::kUser);
1787 cascade.Add("--y:var(--x)", CascadeOrigin::kUser);
1788 cascade.Add("--x:200px", CascadeOrigin::kAuthor);
1789 cascade.Add("animation:test linear 1000s -500s");
1790 cascade.Apply();
1791
1792 cascade.CalculateAnimationUpdate();
1793 cascade.Apply();
1794
1795 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1796 }
1797
TEST_F(StyleCascadeTest,RevertCausesTransition)1798 TEST_F(StyleCascadeTest, RevertCausesTransition) {
1799 TestCascade cascade1(GetDocument());
1800 cascade1.Add("width:200px", CascadeOrigin::kUser);
1801 cascade1.Add("width:100px", CascadeOrigin::kAuthor);
1802 cascade1.Add("transition: width 1000s steps(2, end)", CascadeOrigin::kAuthor);
1803 cascade1.Apply();
1804
1805 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
1806
1807 // Now simulate a new style, with new color values.
1808 TestCascade cascade2(GetDocument());
1809 cascade2.Add("width:200px", CascadeOrigin::kUser);
1810 cascade2.Add("width:100px", CascadeOrigin::kAuthor);
1811 cascade2.Add("width:revert", CascadeOrigin::kAuthor);
1812 cascade2.Add("transition: width 1000s steps(2, start)",
1813 CascadeOrigin::kAuthor);
1814 cascade2.Apply();
1815
1816 cascade2.CalculateTransitionUpdate();
1817 cascade2.Apply();
1818
1819 EXPECT_EQ("150px", cascade2.ComputedValue("width"));
1820 }
1821
TEST_F(StyleCascadeTest,CSSWideKeywordsInFallbacks)1822 TEST_F(StyleCascadeTest, CSSWideKeywordsInFallbacks) {
1823 {
1824 TestCascade cascade(GetDocument());
1825 cascade.Add("display:var(--u,initial)");
1826 cascade.Add("margin:var(--u,initial)");
1827 cascade.Apply();
1828 }
1829 {
1830 TestCascade cascade(GetDocument());
1831 cascade.Add("display:var(--u,inherit)");
1832 cascade.Add("margin:var(--u,inherit)");
1833 cascade.Apply();
1834 }
1835 {
1836 TestCascade cascade(GetDocument());
1837 cascade.Add("display:var(--u,unset)");
1838 cascade.Add("margin:var(--u,unset)");
1839 cascade.Apply();
1840 }
1841 {
1842 TestCascade cascade(GetDocument());
1843 cascade.Add("display:var(--u,revert)");
1844 cascade.Add("margin:var(--u,revert)");
1845 cascade.Apply();
1846 }
1847
1848 // TODO(crbug.com/1105782): Specs and WPT are currently in conflict
1849 // regarding the correct behavior here. For now this test just verifies
1850 // that we don't crash.
1851 }
1852
TEST_F(StyleCascadeTest,RegisteredInitial)1853 TEST_F(StyleCascadeTest, RegisteredInitial) {
1854 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1855
1856 TestCascade cascade(GetDocument());
1857 cascade.Apply();
1858 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1859 }
1860
TEST_F(StyleCascadeTest,SubstituteRegisteredImplicitInitialValue)1861 TEST_F(StyleCascadeTest, SubstituteRegisteredImplicitInitialValue) {
1862 RegisterProperty(GetDocument(), "--x", "<length>", "13px", false);
1863
1864 TestCascade cascade(GetDocument());
1865 cascade.Add("--y", " var(--x) ");
1866 cascade.Apply();
1867 EXPECT_EQ("13px", cascade.ComputedValue("--x"));
1868 EXPECT_EQ(" 13px ", cascade.ComputedValue("--y"));
1869 }
1870
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversal)1871 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversal) {
1872 RegisterProperty(GetDocument(), "--x", "*", "foo", false);
1873
1874 TestCascade cascade(GetDocument());
1875 cascade.Add("--x", "bar");
1876 cascade.Add("--y", "var(--x)");
1877 cascade.Apply();
1878 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1879 EXPECT_EQ("bar", cascade.ComputedValue("--y"));
1880 }
1881
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversalInvalid)1882 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversalInvalid) {
1883 RegisterProperty(GetDocument(), "--x", "*", base::nullopt, false);
1884
1885 TestCascade cascade(GetDocument());
1886 cascade.Add("--y", " var(--x) ");
1887 cascade.Apply();
1888 EXPECT_FALSE(cascade.ComputedValue("--x"));
1889 EXPECT_FALSE(cascade.ComputedValue("--y"));
1890 }
1891
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversalInitial)1892 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversalInitial) {
1893 RegisterProperty(GetDocument(), "--x", "*", "foo", false);
1894
1895 TestCascade cascade(GetDocument());
1896 cascade.Add("--y", " var(--x) ");
1897 cascade.Apply();
1898 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1899 EXPECT_EQ(" foo ", cascade.ComputedValue("--y"));
1900 }
1901
TEST_F(StyleCascadeTest,RegisteredExplicitInitial)1902 TEST_F(StyleCascadeTest, RegisteredExplicitInitial) {
1903 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1904
1905 TestCascade cascade(GetDocument());
1906 cascade.Add("--x", "10px");
1907 cascade.Apply();
1908 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
1909
1910 cascade.Reset();
1911 cascade.Add("--x", "initial");
1912 cascade.Add("--y", "var(--x)");
1913 cascade.Apply();
1914 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1915 EXPECT_EQ("0px", cascade.ComputedValue("--y"));
1916 }
1917
TEST_F(StyleCascadeTest,RegisteredExplicitInherit)1918 TEST_F(StyleCascadeTest, RegisteredExplicitInherit) {
1919 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1920
1921 TestCascade parent(GetDocument());
1922 parent.Add("--x", "15px");
1923 parent.Apply();
1924 EXPECT_EQ("15px", parent.ComputedValue("--x"));
1925
1926 TestCascade cascade(GetDocument());
1927 cascade.InheritFrom(parent.TakeStyle());
1928 cascade.Apply();
1929 EXPECT_EQ("0px", cascade.ComputedValue("--x")); // Note: inherit==false
1930
1931 cascade.Reset();
1932 cascade.Add("--x", "inherit");
1933 cascade.Add("--y", "var(--x)");
1934 cascade.Apply();
1935 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1936 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1937 }
1938
TEST_F(StyleCascadeTest,RegisteredExplicitUnset)1939 TEST_F(StyleCascadeTest, RegisteredExplicitUnset) {
1940 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1941 RegisterProperty(GetDocument(), "--y", "<length>", "0px", true);
1942
1943 TestCascade parent(GetDocument());
1944 parent.Add("--x", "15px");
1945 parent.Add("--y", "15px");
1946 parent.Apply();
1947 EXPECT_EQ("15px", parent.ComputedValue("--x"));
1948 EXPECT_EQ("15px", parent.ComputedValue("--y"));
1949
1950 TestCascade cascade(GetDocument());
1951 cascade.InheritFrom(parent.TakeStyle());
1952 cascade.Add("--x", "2px");
1953 cascade.Add("--y", "2px");
1954 cascade.Apply();
1955 EXPECT_EQ("2px", cascade.ComputedValue("--x"));
1956 EXPECT_EQ("2px", cascade.ComputedValue("--y"));
1957
1958 cascade.Reset();
1959 cascade.Add("--x", "unset");
1960 cascade.Add("--y", "unset");
1961 cascade.Add("--z", "var(--x) var(--y)");
1962 cascade.Apply();
1963 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1964 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1965 EXPECT_EQ("0px 15px", cascade.ComputedValue("--z"));
1966 }
1967
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInCustomProperty)1968 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInCustomProperty) {
1969 TestCascade cascade(GetDocument());
1970 cascade.Add(AnimationTaintedSet("--x", "15px"));
1971 cascade.Add("--y", "var(--x)");
1972 cascade.Apply();
1973 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1974 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1975 }
1976
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInStandardProperty)1977 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInStandardProperty) {
1978 TestCascade cascade(GetDocument());
1979 cascade.Add(AnimationTaintedSet("--x", "15px"));
1980 cascade.Add("width", "var(--x)");
1981 cascade.Apply();
1982 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1983 EXPECT_EQ("15px", cascade.ComputedValue("width"));
1984 }
1985
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInAnimationProperty)1986 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInAnimationProperty) {
1987 TestCascade cascade(GetDocument());
1988 cascade.Add("--x", "20s");
1989 cascade.Add("animation-duration", "var(--x)");
1990 cascade.Apply();
1991
1992 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
1993 EXPECT_EQ("20s", cascade.ComputedValue("animation-duration"));
1994
1995 cascade.Reset();
1996 cascade.Add(AnimationTaintedSet("--y", "20s"));
1997 cascade.Add("animation-duration", "var(--y)");
1998 cascade.Apply();
1999
2000 EXPECT_EQ("20s", cascade.ComputedValue("--y"));
2001 EXPECT_EQ("0s", cascade.ComputedValue("animation-duration"));
2002 }
2003
TEST_F(StyleCascadeTest,IndirectlyAnimationTainted)2004 TEST_F(StyleCascadeTest, IndirectlyAnimationTainted) {
2005 TestCascade cascade(GetDocument());
2006 cascade.Add(AnimationTaintedSet("--x", "20s"));
2007 cascade.Add("--y", "var(--x)");
2008 cascade.Add("animation-duration", "var(--y)");
2009 cascade.Apply();
2010
2011 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
2012 EXPECT_EQ("20s", cascade.ComputedValue("--y"));
2013 EXPECT_EQ("0s", cascade.ComputedValue("animation-duration"));
2014 }
2015
TEST_F(StyleCascadeTest,AnimationTaintedFallback)2016 TEST_F(StyleCascadeTest, AnimationTaintedFallback) {
2017 TestCascade cascade(GetDocument());
2018 cascade.Add(AnimationTaintedSet("--x", "20s"));
2019 cascade.Add("animation-duration", "var(--x,1s)");
2020 cascade.Apply();
2021
2022 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
2023 EXPECT_EQ("1s", cascade.ComputedValue("animation-duration"));
2024 }
2025
TEST_F(StyleCascadeTest,EnvMissingNestedVar)2026 TEST_F(StyleCascadeTest, EnvMissingNestedVar) {
2027 TestCascade cascade(GetDocument());
2028 cascade.Add("--x", "rgb(0, 0, 0)");
2029 cascade.Add("background-color", "env(missing, var(--x))");
2030 cascade.Apply();
2031
2032 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("--x"));
2033 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("background-color"));
2034 }
2035
TEST_F(StyleCascadeTest,EnvMissingNestedVarFallback)2036 TEST_F(StyleCascadeTest, EnvMissingNestedVarFallback) {
2037 TestCascade cascade(GetDocument());
2038 cascade.Add("background-color", "env(missing, var(--missing, blue))");
2039 cascade.Apply();
2040
2041 EXPECT_EQ("rgb(0, 0, 255)", cascade.ComputedValue("background-color"));
2042 }
2043
TEST_F(StyleCascadeTest,EnvMissingFallback)2044 TEST_F(StyleCascadeTest, EnvMissingFallback) {
2045 TestCascade cascade(GetDocument());
2046 cascade.Add("background-color", "env(missing, blue)");
2047 cascade.Apply();
2048
2049 EXPECT_EQ("rgb(0, 0, 255)", cascade.ComputedValue("background-color"));
2050 }
2051
TEST_F(StyleCascadeTest,ValidEnv)2052 TEST_F(StyleCascadeTest, ValidEnv) {
2053 AutoEnv env(*this, "test", "red");
2054
2055 TestCascade cascade(GetDocument());
2056 cascade.Add("background-color", "env(test, blue)");
2057 cascade.Apply();
2058
2059 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
2060 }
2061
TEST_F(StyleCascadeTest,ValidEnvFallback)2062 TEST_F(StyleCascadeTest, ValidEnvFallback) {
2063 AutoEnv env(*this, "test", "red");
2064
2065 TestCascade cascade(GetDocument());
2066 cascade.Add("background-color", "env(test, blue)");
2067 cascade.Apply();
2068
2069 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
2070 }
2071
TEST_F(StyleCascadeTest,ValidEnvInUnusedFallback)2072 TEST_F(StyleCascadeTest, ValidEnvInUnusedFallback) {
2073 AutoEnv env(*this, "test", "red");
2074
2075 TestCascade cascade(GetDocument());
2076 cascade.Add("--x", "rgb(0, 0, 0)");
2077 cascade.Add("background-color", "var(--x, env(test))");
2078 cascade.Apply();
2079
2080 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("--x"));
2081 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("background-color"));
2082 }
2083
TEST_F(StyleCascadeTest,ValidEnvInUsedFallback)2084 TEST_F(StyleCascadeTest, ValidEnvInUsedFallback) {
2085 AutoEnv env(*this, "test", "red");
2086
2087 TestCascade cascade(GetDocument());
2088 cascade.Add("background-color", "var(--missing, env(test))");
2089 cascade.Apply();
2090
2091 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
2092 }
2093
TEST_F(StyleCascadeTest,AnimationApplyFilter)2094 TEST_F(StyleCascadeTest, AnimationApplyFilter) {
2095 AppendSheet(R"HTML(
2096 @keyframes test {
2097 from { color: white; background-color: white; }
2098 to { color: gray; background-color: gray; }
2099 }
2100 )HTML");
2101
2102 TestCascade cascade(GetDocument());
2103
2104 cascade.Add("animation: test linear 10s -5s");
2105 cascade.Add("color:green");
2106 cascade.Apply();
2107
2108 cascade.CalculateAnimationUpdate();
2109 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
2110
2111 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2112 EXPECT_EQ("rgb(192, 192, 192)", cascade.ComputedValue("background-color"));
2113 }
2114
TEST_F(StyleCascadeTest,TransitionApplyFilter)2115 TEST_F(StyleCascadeTest, TransitionApplyFilter) {
2116 TestCascade cascade1(GetDocument());
2117 cascade1.Add("background-color: white");
2118 cascade1.Add("color: white");
2119 cascade1.Add("transition: all steps(2, start) 100s");
2120 cascade1.Apply();
2121
2122 // Set the old style on the element, so that the transition
2123 // update detects it.
2124 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
2125
2126 // Now simulate a new style, with new color values.
2127 TestCascade cascade2(GetDocument());
2128 cascade2.Add("background-color: gray");
2129 cascade2.Add("color: gray");
2130 cascade2.Add("transition: all steps(2, start) 100s");
2131 cascade2.Apply();
2132
2133 cascade2.CalculateTransitionUpdate();
2134 cascade2.Apply(CascadeFilter(CSSProperty::kInherited, true));
2135
2136 EXPECT_EQ("rgb(128, 128, 128)", cascade2.ComputedValue("color"));
2137 EXPECT_EQ("rgb(192, 192, 192)", cascade2.ComputedValue("background-color"));
2138 }
2139
TEST_F(StyleCascadeTest,PendingKeyframeAnimation)2140 TEST_F(StyleCascadeTest, PendingKeyframeAnimation) {
2141 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2142
2143 AppendSheet(R"HTML(
2144 @keyframes test {
2145 from { --x: 10px; }
2146 to { --x: 20px; }
2147 }
2148 )HTML");
2149
2150 TestCascade cascade(GetDocument());
2151
2152 cascade.Add("animation-name", "test");
2153 cascade.Add("animation-duration", "1s");
2154 cascade.Apply();
2155
2156 cascade.CalculateAnimationUpdate();
2157 cascade.Apply();
2158
2159 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
2160 }
2161
TEST_F(StyleCascadeTest,PendingKeyframeAnimationApply)2162 TEST_F(StyleCascadeTest, PendingKeyframeAnimationApply) {
2163 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2164
2165 AppendSheet(R"HTML(
2166 @keyframes test {
2167 from { --x: 10px; }
2168 to { --x: 20px; }
2169 }
2170 )HTML");
2171
2172 TestCascade cascade(GetDocument());
2173
2174 cascade.Add("animation-name", "test");
2175 cascade.Add("animation-duration", "10s");
2176 cascade.Add("animation-timing-function", "linear");
2177 cascade.Add("animation-delay", "-5s");
2178 cascade.Apply();
2179
2180 cascade.CalculateAnimationUpdate();
2181 cascade.Apply();
2182
2183 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
2184 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
2185 }
2186
TEST_F(StyleCascadeTest,TransitionCausesInterpolationValue)2187 TEST_F(StyleCascadeTest, TransitionCausesInterpolationValue) {
2188 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2189
2190 // First, simulate an "old style".
2191 TestCascade cascade1(GetDocument());
2192 cascade1.Add("--x", "10px");
2193 cascade1.Add("transition", "--x 1s");
2194 cascade1.Apply();
2195
2196 // Set the old style on the element, so that the animation
2197 // update detects it.
2198 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
2199
2200 // Now simulate a new style, with a new value for --x.
2201 TestCascade cascade2(GetDocument());
2202 cascade2.Add("--x", "20px");
2203 cascade2.Add("transition", "--x 1s");
2204 cascade2.Apply();
2205
2206 cascade2.CalculateTransitionUpdate();
2207 cascade2.Apply();
2208
2209 EXPECT_EQ(CascadeOrigin::kTransition,
2210 cascade2.GetPriority("--x").GetOrigin());
2211 }
2212
TEST_F(StyleCascadeTest,TransitionDetectedForChangedFontSize)2213 TEST_F(StyleCascadeTest, TransitionDetectedForChangedFontSize) {
2214 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2215
2216 TestCascade cascade1(GetDocument());
2217 cascade1.Add("font-size", "10px");
2218 cascade1.Add("--x", "10em");
2219 cascade1.Add("width", "10em");
2220 cascade1.Add("height", "10px");
2221 cascade1.Add("transition", "--x 1s, width 1s");
2222 cascade1.Apply();
2223
2224 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
2225
2226 TestCascade cascade2(GetDocument());
2227 cascade2.Add("font-size", "20px");
2228 cascade2.Add("--x", "10em");
2229 cascade2.Add("width", "10em");
2230 cascade2.Add("height", "10px");
2231 cascade2.Add("transition", "--x 1s, width 1s");
2232 cascade2.Apply();
2233
2234 cascade2.CalculateTransitionUpdate();
2235 cascade2.Apply();
2236
2237 EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("--x"));
2238 EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("width"));
2239 EXPECT_EQ("10px", cascade2.ComputedValue("height"));
2240 }
2241
TEST_F(StyleCascadeTest,AnimatingVarReferences)2242 TEST_F(StyleCascadeTest, AnimatingVarReferences) {
2243 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2244
2245 AppendSheet(R"HTML(
2246 @keyframes test {
2247 from { --x: var(--from); }
2248 to { --x: var(--to); }
2249 }
2250 )HTML");
2251
2252 TestCascade cascade(GetDocument());
2253
2254 cascade.Add("animation-name", "test");
2255 cascade.Add("animation-duration", "10s");
2256 cascade.Add("animation-timing-function", "linear");
2257 cascade.Add("animation-delay", "-5s");
2258 cascade.Add("--from", "10px");
2259 cascade.Add("--to", "20px");
2260 cascade.Add("--y", "var(--x)");
2261 cascade.Apply();
2262
2263 cascade.CalculateAnimationUpdate();
2264 cascade.Apply();
2265
2266 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
2267 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
2268 }
2269
TEST_F(StyleCascadeTest,AnimateStandardProperty)2270 TEST_F(StyleCascadeTest, AnimateStandardProperty) {
2271 AppendSheet(R"HTML(
2272 @keyframes test {
2273 from { width: 10px; }
2274 to { width: 20px; }
2275 }
2276 )HTML");
2277
2278 TestCascade cascade(GetDocument());
2279
2280 cascade.Add("animation-name", "test");
2281 cascade.Add("animation-duration", "10s");
2282 cascade.Add("animation-timing-function", "linear");
2283 cascade.Add("animation-delay", "-5s");
2284 cascade.Apply();
2285
2286 cascade.CalculateAnimationUpdate();
2287 cascade.Apply();
2288
2289 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
2290 EXPECT_EQ("15px", cascade.ComputedValue("width"));
2291 }
2292
TEST_F(StyleCascadeTest,AnimateLogicalProperty)2293 TEST_F(StyleCascadeTest, AnimateLogicalProperty) {
2294 // We don't support smooth interpolation of css-logical properties yet,
2295 // so this test uses a paused animation at t=0.
2296 // TODO(crbug.com/865579): Support animations of css-logical properties
2297
2298 AppendSheet(R"HTML(
2299 @keyframes test {
2300 from { margin-inline-start: 10px; }
2301 to { margin-inline-start: 20px; }
2302 }
2303 )HTML");
2304
2305 TestCascade cascade(GetDocument());
2306
2307 cascade.Add("margin-left:1000px");
2308 cascade.Add("animation:test 1s linear paused");
2309 cascade.Apply();
2310
2311 cascade.CalculateAnimationUpdate();
2312 cascade.Apply();
2313
2314 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
2315 EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
2316 }
2317
TEST_F(StyleCascadeTest,AnimateLogicalPropertyWithLookup)2318 TEST_F(StyleCascadeTest, AnimateLogicalPropertyWithLookup) {
2319 // We don't support smooth interpolation of css-logical properties yet,
2320 // so this test uses a paused animation at t=0.
2321 // TODO(crbug.com/865579): Support animations of css-logical properties
2322
2323 AppendSheet(R"HTML(
2324 @keyframes test {
2325 from { margin-inline-start: 10px; }
2326 to { margin-inline-start: 20px; }
2327 }
2328 )HTML");
2329
2330 TestCascade cascade(GetDocument());
2331
2332 cascade.Add("margin-left:1000px");
2333 cascade.Add("animation:test 1s linear paused");
2334 cascade.Apply();
2335
2336 cascade.CalculateAnimationUpdate();
2337 cascade.ApplySingle(GetCSSPropertyMarginLeft());
2338
2339 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
2340 EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
2341 }
2342
TEST_F(StyleCascadeTest,AuthorImportantWinOverAnimations)2343 TEST_F(StyleCascadeTest, AuthorImportantWinOverAnimations) {
2344 AppendSheet(R"HTML(
2345 @keyframes test {
2346 from { width: 10px; height: 10px; }
2347 to { width: 20px; height: 20px; }
2348 }
2349 )HTML");
2350
2351 TestCascade cascade(GetDocument());
2352
2353 cascade.Add("animation-name", "test");
2354 cascade.Add("animation-duration", "10s");
2355 cascade.Add("animation-timing-function", "linear");
2356 cascade.Add("animation-delay", "-5s");
2357 cascade.Add("width:40px");
2358 cascade.Add("height:40px !important");
2359 cascade.Apply();
2360
2361 cascade.CalculateAnimationUpdate();
2362 cascade.Apply();
2363
2364 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
2365 EXPECT_EQ(CascadeOrigin::kAuthor, cascade.GetOrigin("height"));
2366
2367 EXPECT_EQ("15px", cascade.ComputedValue("width"));
2368 EXPECT_EQ("40px", cascade.ComputedValue("height"));
2369 }
2370
TEST_F(StyleCascadeTest,TransitionsWinOverAuthorImportant)2371 TEST_F(StyleCascadeTest, TransitionsWinOverAuthorImportant) {
2372 // First, simulate an "old style".
2373 TestCascade cascade1(GetDocument());
2374 cascade1.Add("width:10px !important");
2375 cascade1.Add("height:10px !important");
2376 cascade1.Add("transition:all 1s");
2377 cascade1.Apply();
2378
2379 // Set the old style on the element, so that the animation
2380 // update detects it.
2381 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
2382
2383 // Now simulate a new style, with a new value for width/height.
2384 TestCascade cascade2(GetDocument());
2385 cascade2.Add("width:20px !important");
2386 cascade2.Add("height:20px !important");
2387 cascade2.Add("transition:all 1s");
2388 cascade2.Apply();
2389
2390 cascade2.CalculateTransitionUpdate();
2391 cascade2.Apply();
2392
2393 EXPECT_EQ(CascadeOrigin::kTransition,
2394 cascade2.GetPriority("width").GetOrigin());
2395 EXPECT_EQ(CascadeOrigin::kTransition,
2396 cascade2.GetPriority("height").GetOrigin());
2397 }
2398
TEST_F(StyleCascadeTest,EmRespondsToAnimatedFontSize)2399 TEST_F(StyleCascadeTest, EmRespondsToAnimatedFontSize) {
2400 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2401
2402 AppendSheet(R"HTML(
2403 @keyframes test {
2404 from { font-size: 10px; }
2405 to { font-size: 20px; }
2406 }
2407 )HTML");
2408
2409 TestCascade cascade(GetDocument());
2410
2411 cascade.Add("animation-name", "test");
2412 cascade.Add("animation-duration", "10s");
2413 cascade.Add("animation-timing-function", "linear");
2414 cascade.Add("animation-delay", "-5s");
2415 cascade.Add("--x", "2em");
2416 cascade.Add("width", "10em");
2417 cascade.Apply();
2418
2419 cascade.CalculateAnimationUpdate();
2420 cascade.Apply();
2421
2422 EXPECT_EQ("30px", cascade.ComputedValue("--x"));
2423 EXPECT_EQ("150px", cascade.ComputedValue("width"));
2424 }
2425
TEST_F(StyleCascadeTest,AnimateStandardPropertyWithVar)2426 TEST_F(StyleCascadeTest, AnimateStandardPropertyWithVar) {
2427 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2428
2429 AppendSheet(R"HTML(
2430 @keyframes test {
2431 from { width: var(--from); }
2432 to { width: var(--to); }
2433 }
2434 )HTML");
2435
2436 TestCascade cascade(GetDocument());
2437
2438 cascade.Add("animation-name", "test");
2439 cascade.Add("animation-duration", "10s");
2440 cascade.Add("animation-timing-function", "linear");
2441 cascade.Add("animation-delay", "-5s");
2442 cascade.Add("--from", "10px");
2443 cascade.Add("--to", "20px");
2444 cascade.Apply();
2445
2446 cascade.CalculateAnimationUpdate();
2447 cascade.Apply();
2448
2449 EXPECT_EQ("15px", cascade.ComputedValue("width"));
2450 }
2451
TEST_F(StyleCascadeTest,AnimateStandardShorthand)2452 TEST_F(StyleCascadeTest, AnimateStandardShorthand) {
2453 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2454
2455 AppendSheet(R"HTML(
2456 @keyframes test {
2457 from { margin: 10px; }
2458 to { margin: 20px; }
2459 }
2460 )HTML");
2461
2462 TestCascade cascade(GetDocument());
2463
2464 cascade.Add("animation-name", "test");
2465 cascade.Add("animation-duration", "10s");
2466 cascade.Add("animation-timing-function", "linear");
2467 cascade.Add("animation-delay", "-5s");
2468 cascade.Apply();
2469
2470 cascade.CalculateAnimationUpdate();
2471 cascade.Apply();
2472
2473 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
2474 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right"));
2475 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom"));
2476 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
2477
2478 EXPECT_EQ("15px", cascade.ComputedValue("margin-top"));
2479 EXPECT_EQ("15px", cascade.ComputedValue("margin-right"));
2480 EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom"));
2481 EXPECT_EQ("15px", cascade.ComputedValue("margin-left"));
2482 }
2483
TEST_F(StyleCascadeTest,AnimatedVisitedImportantOverride)2484 TEST_F(StyleCascadeTest, AnimatedVisitedImportantOverride) {
2485 AppendSheet(R"HTML(
2486 @keyframes test {
2487 from { background-color: rgb(100, 100, 100); }
2488 to { background-color: rgb(200, 200, 200); }
2489 }
2490 )HTML");
2491
2492 TestCascade cascade(GetDocument());
2493 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
2494
2495 cascade.Add(ParseDeclarationBlock("background-color:red !important"),
2496 CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
2497 cascade.Add("animation-name:test");
2498 cascade.Add("animation-duration:10s");
2499 cascade.Add("animation-timing-function:linear");
2500 cascade.Add("animation-delay:-5s");
2501 cascade.Apply();
2502
2503 cascade.CalculateAnimationUpdate();
2504 cascade.Apply();
2505 EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("background-color"));
2506
2507 auto style = cascade.TakeStyle();
2508
2509 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
2510 EXPECT_EQ(Color(255, 0, 0),
2511 style->VisitedDependentColor(GetCSSPropertyBackgroundColor()));
2512
2513 style->SetInsideLink(EInsideLink::kNotInsideLink);
2514 EXPECT_EQ(Color(150, 150, 150),
2515 style->VisitedDependentColor(GetCSSPropertyBackgroundColor()));
2516 }
2517
TEST_F(StyleCascadeTest,AnimatedVisitedHighPrio)2518 TEST_F(StyleCascadeTest, AnimatedVisitedHighPrio) {
2519 AppendSheet(R"HTML(
2520 @keyframes test {
2521 from { color: rgb(100, 100, 100); }
2522 to { color: rgb(200, 200, 200); }
2523 }
2524 )HTML");
2525
2526 TestCascade cascade(GetDocument());
2527 cascade.Add("color:red");
2528 cascade.Add("animation:test 10s -5s linear");
2529 cascade.Apply();
2530
2531 cascade.CalculateAnimationUpdate();
2532 cascade.Apply();
2533 EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("color"));
2534
2535 auto style = cascade.TakeStyle();
2536
2537 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
2538 EXPECT_EQ(Color(150, 150, 150),
2539 style->VisitedDependentColor(GetCSSPropertyColor()));
2540
2541 style->SetInsideLink(EInsideLink::kNotInsideLink);
2542 EXPECT_EQ(Color(150, 150, 150),
2543 style->VisitedDependentColor(GetCSSPropertyColor()));
2544 }
2545
TEST_F(StyleCascadeTest,AnimatePendingSubstitutionValue)2546 TEST_F(StyleCascadeTest, AnimatePendingSubstitutionValue) {
2547 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2548
2549 AppendSheet(R"HTML(
2550 @keyframes test {
2551 from { margin: var(--from); }
2552 to { margin: var(--to); }
2553 }
2554 )HTML");
2555
2556 TestCascade cascade(GetDocument());
2557
2558 cascade.Add("animation-name", "test");
2559 cascade.Add("animation-duration", "10s");
2560 cascade.Add("animation-timing-function", "linear");
2561 cascade.Add("animation-delay", "-5s");
2562 cascade.Add("--from", "10px");
2563 cascade.Add("--to", "20px");
2564 cascade.Apply();
2565
2566 cascade.CalculateAnimationUpdate();
2567 cascade.Apply();
2568
2569 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
2570 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right"));
2571 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom"));
2572 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
2573
2574 EXPECT_EQ("15px", cascade.ComputedValue("margin-top"));
2575 EXPECT_EQ("15px", cascade.ComputedValue("margin-right"));
2576 EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom"));
2577 EXPECT_EQ("15px", cascade.ComputedValue("margin-left"));
2578 }
2579
TEST_F(StyleCascadeTest,ZoomCascadeOrder)2580 TEST_F(StyleCascadeTest, ZoomCascadeOrder) {
2581 TestCascade cascade(GetDocument());
2582 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
2583 cascade.Add("zoom:normal", CascadeOrigin::kUserAgent);
2584 cascade.Apply();
2585
2586 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
2587 }
2588
TEST_F(StyleCascadeTest,ZoomVsAll)2589 TEST_F(StyleCascadeTest, ZoomVsAll) {
2590 TestCascade cascade(GetDocument());
2591 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
2592 cascade.Add("all:initial");
2593 cascade.Apply();
2594
2595 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
2596 }
2597
TEST_F(StyleCascadeTest,ZoomReversedCascadeOrder)2598 TEST_F(StyleCascadeTest, ZoomReversedCascadeOrder) {
2599 TestCascade cascade(GetDocument());
2600 cascade.Add("zoom:normal", CascadeOrigin::kUserAgent);
2601 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
2602 cascade.Apply();
2603
2604 EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
2605 }
2606
TEST_F(StyleCascadeTest,ZoomImportant)2607 TEST_F(StyleCascadeTest, ZoomImportant) {
2608 TestCascade cascade(GetDocument());
2609 cascade.Add("zoom:200% !important", CascadeOrigin::kUserAgent);
2610 cascade.Add("zoom:normal", CascadeOrigin::kAuthor);
2611 cascade.Apply();
2612
2613 EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
2614 }
2615
TEST_F(StyleCascadeTest,WritingModeCascadeOrder)2616 TEST_F(StyleCascadeTest, WritingModeCascadeOrder) {
2617 TestCascade cascade(GetDocument());
2618 cascade.Add("writing-mode", "vertical-lr");
2619 cascade.Add("-webkit-writing-mode", "vertical-rl");
2620 cascade.Apply();
2621
2622 EXPECT_EQ("vertical-rl", cascade.ComputedValue("writing-mode"));
2623 EXPECT_EQ("vertical-rl", cascade.ComputedValue("-webkit-writing-mode"));
2624 }
2625
TEST_F(StyleCascadeTest,WritingModeReversedCascadeOrder)2626 TEST_F(StyleCascadeTest, WritingModeReversedCascadeOrder) {
2627 TestCascade cascade(GetDocument());
2628 cascade.Add("-webkit-writing-mode", "vertical-rl");
2629 cascade.Add("writing-mode", "vertical-lr");
2630 cascade.Apply();
2631
2632 EXPECT_EQ("vertical-lr", cascade.ComputedValue("writing-mode"));
2633 EXPECT_EQ("vertical-lr", cascade.ComputedValue("-webkit-writing-mode"));
2634 }
2635
TEST_F(StyleCascadeTest,WritingModePriority)2636 TEST_F(StyleCascadeTest, WritingModePriority) {
2637 TestCascade cascade(GetDocument());
2638 cascade.Add("writing-mode:vertical-lr !important", Origin::kAuthor);
2639 cascade.Add("-webkit-writing-mode:vertical-rl", Origin::kAuthor);
2640 cascade.Apply();
2641
2642 EXPECT_EQ("vertical-lr", cascade.ComputedValue("writing-mode"));
2643 EXPECT_EQ("vertical-lr", cascade.ComputedValue("-webkit-writing-mode"));
2644 }
2645
TEST_F(StyleCascadeTest,RubyPositionCascadeOrder)2646 TEST_F(StyleCascadeTest, RubyPositionCascadeOrder) {
2647 TestCascade cascade(GetDocument());
2648 cascade.Add("ruby-position", "over");
2649 cascade.Add("-webkit-ruby-position", "after");
2650 cascade.Apply();
2651
2652 EXPECT_EQ("under", cascade.ComputedValue("ruby-position"));
2653 EXPECT_EQ("after", cascade.ComputedValue("-webkit-ruby-position"));
2654 }
2655
TEST_F(StyleCascadeTest,RubyPositionReverseCascadeOrder)2656 TEST_F(StyleCascadeTest, RubyPositionReverseCascadeOrder) {
2657 TestCascade cascade(GetDocument());
2658 cascade.Add("-webkit-ruby-position", "after");
2659 cascade.Add("ruby-position", "over");
2660 cascade.Apply();
2661
2662 EXPECT_EQ("over", cascade.ComputedValue("ruby-position"));
2663 EXPECT_EQ("before", cascade.ComputedValue("-webkit-ruby-position"));
2664 }
2665
TEST_F(StyleCascadeTest,RubyPositionSurrogateCanCascadeAsOriginal)2666 TEST_F(StyleCascadeTest, RubyPositionSurrogateCanCascadeAsOriginal) {
2667 // Note: ruby-position is defined as the surrogate, and -webkit-ruby-position
2668 // is the original.
2669 ASSERT_TRUE(GetCSSPropertyRubyPosition().IsSurrogate());
2670 ASSERT_FALSE(GetCSSPropertyWebkitRubyPosition().IsSurrogate());
2671
2672 const struct {
2673 CSSValueID specified;
2674 const char* webkit_expected;
2675 const char* unprefixed_expected;
2676 } tests[] = {
2677 {CSSValueID::kBefore, "before", "over"},
2678 {CSSValueID::kAfter, "after", "under"},
2679 {CSSValueID::kOver, "before", "over"},
2680 {CSSValueID::kUnder, "after", "under"},
2681 };
2682
2683 for (const auto& test : tests) {
2684 TestCascade cascade(GetDocument());
2685 auto* set =
2686 MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
2687 set->SetProperty(CSSPropertyID::kWebkitRubyPosition,
2688 *CSSIdentifierValue::Create(test.specified));
2689 cascade.Add(set);
2690 cascade.Apply();
2691 EXPECT_EQ(test.unprefixed_expected, cascade.ComputedValue("ruby-position"));
2692 EXPECT_EQ(test.webkit_expected,
2693 cascade.ComputedValue("-webkit-ruby-position"));
2694 }
2695 }
2696
TEST_F(StyleCascadeTest,TextOrientationPriority)2697 TEST_F(StyleCascadeTest, TextOrientationPriority) {
2698 TestCascade cascade(GetDocument());
2699 cascade.Add("text-orientation:upright !important");
2700 cascade.Add("-webkit-text-orientation:sideways");
2701 cascade.Apply();
2702
2703 EXPECT_EQ("upright", cascade.ComputedValue("text-orientation"));
2704 EXPECT_EQ("upright", cascade.ComputedValue("-webkit-text-orientation"));
2705 }
2706
TEST_F(StyleCascadeTest,TextOrientationRevert)2707 TEST_F(StyleCascadeTest, TextOrientationRevert) {
2708 TestCascade cascade(GetDocument());
2709 cascade.Add("text-orientation:upright", CascadeOrigin::kUserAgent);
2710 cascade.Add("-webkit-text-orientation:mixed");
2711 cascade.Add("-webkit-text-orientation:revert");
2712 cascade.Apply();
2713
2714 EXPECT_EQ("upright", cascade.ComputedValue("text-orientation"));
2715 EXPECT_EQ("upright", cascade.ComputedValue("-webkit-text-orientation"));
2716 }
2717
TEST_F(StyleCascadeTest,TextOrientationLegacyKeyword)2718 TEST_F(StyleCascadeTest, TextOrientationLegacyKeyword) {
2719 TestCascade cascade(GetDocument());
2720 cascade.Add("-webkit-text-orientation:vertical-right");
2721 cascade.Apply();
2722
2723 EXPECT_EQ("mixed", cascade.ComputedValue("text-orientation"));
2724 EXPECT_EQ("vertical-right",
2725 cascade.ComputedValue("-webkit-text-orientation"));
2726 }
2727
TEST_F(StyleCascadeTest,WebkitBorderImageCascadeOrder)2728 TEST_F(StyleCascadeTest, WebkitBorderImageCascadeOrder) {
2729 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2730 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2731
2732 TestCascade cascade(GetDocument());
2733 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2734 Origin::kAuthor);
2735 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2736 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2737 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2738 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2739 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2740 cascade.Apply();
2741
2742 EXPECT_EQ(gradient2, cascade.ComputedValue("border-image-source"));
2743 EXPECT_EQ("20", cascade.ComputedValue("border-image-slice"));
2744 EXPECT_EQ("6px", cascade.ComputedValue("border-image-width"));
2745 EXPECT_EQ("4px", cascade.ComputedValue("border-image-outset"));
2746 EXPECT_EQ("space", cascade.ComputedValue("border-image-repeat"));
2747 }
2748
TEST_F(StyleCascadeTest,WebkitBorderImageReverseCascadeOrder)2749 TEST_F(StyleCascadeTest, WebkitBorderImageReverseCascadeOrder) {
2750 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2751 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2752
2753 TestCascade cascade(GetDocument());
2754 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2755 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2756 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2757 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2758 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2759 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2760 Origin::kAuthor);
2761 cascade.Apply();
2762
2763 EXPECT_EQ(gradient1, cascade.ComputedValue("border-image-source"));
2764 EXPECT_EQ("40 fill", cascade.ComputedValue("border-image-slice"));
2765 EXPECT_EQ("10px", cascade.ComputedValue("border-image-width"));
2766 EXPECT_EQ("20px", cascade.ComputedValue("border-image-outset"));
2767 EXPECT_EQ("round", cascade.ComputedValue("border-image-repeat"));
2768 }
2769
TEST_F(StyleCascadeTest,WebkitBorderImageMixedOrder)2770 TEST_F(StyleCascadeTest, WebkitBorderImageMixedOrder) {
2771 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2772 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2773
2774 TestCascade cascade(GetDocument());
2775 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2776 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2777 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2778 Origin::kAuthor);
2779 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2780 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2781 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2782 cascade.Apply();
2783
2784 EXPECT_EQ(gradient1, cascade.ComputedValue("border-image-source"));
2785 EXPECT_EQ("20", cascade.ComputedValue("border-image-slice"));
2786 EXPECT_EQ("10px", cascade.ComputedValue("border-image-width"));
2787 EXPECT_EQ("4px", cascade.ComputedValue("border-image-outset"));
2788 EXPECT_EQ("space", cascade.ComputedValue("border-image-repeat"));
2789 }
2790
TEST_F(StyleCascadeTest,InitialDirection)2791 TEST_F(StyleCascadeTest, InitialDirection) {
2792 TestCascade cascade(GetDocument());
2793 cascade.Add("margin-inline-start:10px");
2794 cascade.Add("margin-inline-end:20px");
2795 cascade.Apply();
2796
2797 EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
2798 EXPECT_EQ("20px", cascade.ComputedValue("margin-right"));
2799 }
2800
TEST_F(StyleCascadeTest,NonInitialDirection)2801 TEST_F(StyleCascadeTest, NonInitialDirection) {
2802 TestCascade cascade(GetDocument());
2803 cascade.Add("margin-inline-start:10px");
2804 cascade.Add("margin-inline-end:20px");
2805 cascade.Add("direction:rtl");
2806 cascade.Apply();
2807
2808 EXPECT_EQ("20px", cascade.ComputedValue("margin-left"));
2809 EXPECT_EQ("10px", cascade.ComputedValue("margin-right"));
2810 }
2811
TEST_F(StyleCascadeTest,InitialWritingMode)2812 TEST_F(StyleCascadeTest, InitialWritingMode) {
2813 TestCascade cascade(GetDocument());
2814 cascade.Add("inline-size:10px");
2815 cascade.Add("block-size:20px");
2816 cascade.Apply();
2817
2818 EXPECT_EQ("10px", cascade.ComputedValue("width"));
2819 EXPECT_EQ("20px", cascade.ComputedValue("height"));
2820 }
2821
TEST_F(StyleCascadeTest,NonInitialWritingMode)2822 TEST_F(StyleCascadeTest, NonInitialWritingMode) {
2823 TestCascade cascade(GetDocument());
2824 cascade.Add("inline-size:10px");
2825 cascade.Add("block-size:20px");
2826 cascade.Add("writing-mode:vertical-lr");
2827 cascade.Apply();
2828
2829 EXPECT_EQ("20px", cascade.ComputedValue("width"));
2830 EXPECT_EQ("10px", cascade.ComputedValue("height"));
2831 }
2832
TEST_F(StyleCascadeTest,DoesNotDependOnCascadeAffectingProperty)2833 TEST_F(StyleCascadeTest, DoesNotDependOnCascadeAffectingProperty) {
2834 TestCascade cascade(GetDocument());
2835 cascade.Add("width:10px");
2836 cascade.Add("height:20px");
2837 cascade.Apply();
2838
2839 EXPECT_FALSE(cascade.DependsOnCascadeAffectingProperty());
2840 EXPECT_EQ("10px", cascade.ComputedValue("width"));
2841 EXPECT_EQ("20px", cascade.ComputedValue("height"));
2842 }
2843
TEST_F(StyleCascadeTest,DependsOnCascadeAffectingProperty)2844 TEST_F(StyleCascadeTest, DependsOnCascadeAffectingProperty) {
2845 TestCascade cascade(GetDocument());
2846 cascade.Add("inline-size:10px");
2847 cascade.Add("height:20px");
2848 cascade.Apply();
2849
2850 EXPECT_TRUE(cascade.DependsOnCascadeAffectingProperty());
2851 EXPECT_EQ("10px", cascade.ComputedValue("width"));
2852 EXPECT_EQ("20px", cascade.ComputedValue("height"));
2853 }
2854
TEST_F(StyleCascadeTest,ResetDependsOnCascadeAffectingPropertyFlag)2855 TEST_F(StyleCascadeTest, ResetDependsOnCascadeAffectingPropertyFlag) {
2856 TestCascade cascade(GetDocument());
2857 cascade.Add("inline-size:10px");
2858 cascade.Add("height:20px");
2859 cascade.Apply();
2860
2861 EXPECT_TRUE(cascade.DependsOnCascadeAffectingProperty());
2862 cascade.Reset();
2863 EXPECT_FALSE(cascade.DependsOnCascadeAffectingProperty());
2864 }
2865
TEST_F(StyleCascadeTest,MarkReferenced)2866 TEST_F(StyleCascadeTest, MarkReferenced) {
2867 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2868 RegisterProperty(GetDocument(), "--y", "<length>", "0px", false);
2869
2870 TestCascade cascade(GetDocument());
2871 cascade.Add("width", "var(--x)");
2872 cascade.Apply();
2873
2874 const auto& registry = GetDocument().EnsurePropertyRegistry();
2875
2876 EXPECT_TRUE(registry.WasReferenced("--x"));
2877 EXPECT_FALSE(registry.WasReferenced("--y"));
2878 }
2879
TEST_F(StyleCascadeTest,MarkHasVariableReferenceLonghand)2880 TEST_F(StyleCascadeTest, MarkHasVariableReferenceLonghand) {
2881 TestCascade cascade(GetDocument());
2882 cascade.Add("--x", "1px");
2883 cascade.Add("width", "var(--x)");
2884 cascade.Apply();
2885 auto style = cascade.TakeStyle();
2886 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2887 }
2888
TEST_F(StyleCascadeTest,MarkHasVariableReferenceShorthand)2889 TEST_F(StyleCascadeTest, MarkHasVariableReferenceShorthand) {
2890 TestCascade cascade(GetDocument());
2891 cascade.Add("--x", "1px");
2892 cascade.Add("margin", "var(--x)");
2893 cascade.Apply();
2894 auto style = cascade.TakeStyle();
2895 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2896 }
2897
TEST_F(StyleCascadeTest,MarkHasVariableReferenceLonghandMissingVar)2898 TEST_F(StyleCascadeTest, MarkHasVariableReferenceLonghandMissingVar) {
2899 TestCascade cascade(GetDocument());
2900 cascade.Add("width", "var(--x)");
2901 cascade.Apply();
2902 auto style = cascade.TakeStyle();
2903 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2904 }
2905
TEST_F(StyleCascadeTest,MarkHasVariableReferenceShorthandMissingVar)2906 TEST_F(StyleCascadeTest, MarkHasVariableReferenceShorthandMissingVar) {
2907 TestCascade cascade(GetDocument());
2908 cascade.Add("margin", "var(--x)");
2909 cascade.Apply();
2910 auto style = cascade.TakeStyle();
2911 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2912 }
2913
TEST_F(StyleCascadeTest,NoMarkHasVariableReferenceInherited)2914 TEST_F(StyleCascadeTest, NoMarkHasVariableReferenceInherited) {
2915 TestCascade cascade(GetDocument());
2916 cascade.Add("color", "var(--x)");
2917 cascade.Apply();
2918 auto style = cascade.TakeStyle();
2919 EXPECT_FALSE(style->HasVariableReferenceFromNonInheritedProperty());
2920 }
2921
TEST_F(StyleCascadeTest,NoMarkHasVariableReferenceWithoutVar)2922 TEST_F(StyleCascadeTest, NoMarkHasVariableReferenceWithoutVar) {
2923 TestCascade cascade(GetDocument());
2924 cascade.Add("width", "1px");
2925 cascade.Apply();
2926 auto style = cascade.TakeStyle();
2927 EXPECT_FALSE(style->HasVariableReferenceFromNonInheritedProperty());
2928 }
2929
TEST_F(StyleCascadeTest,InternalVisitedColorLonghand)2930 TEST_F(StyleCascadeTest, InternalVisitedColorLonghand) {
2931 TestCascade cascade(GetDocument());
2932 cascade.Add("color:green", CascadeOrigin::kAuthor);
2933 cascade.Add("color:red", CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
2934
2935 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
2936 cascade.Apply();
2937
2938 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2939
2940 Color red(255, 0, 0);
2941 const CSSProperty& color = GetCSSPropertyColor();
2942 EXPECT_EQ(red, cascade.TakeStyle()->VisitedDependentColor(color));
2943 }
2944
TEST_F(StyleCascadeTest,VarInInternalVisitedColorShorthand)2945 TEST_F(StyleCascadeTest, VarInInternalVisitedColorShorthand) {
2946 TestCascade cascade(GetDocument());
2947 cascade.Add("--x:red", CascadeOrigin::kAuthor);
2948 cascade.Add("outline:medium solid var(--x)", CascadeOrigin::kAuthor,
2949 CSSSelector::kMatchVisited);
2950 cascade.Add("outline-color:green", CascadeOrigin::kAuthor,
2951 CSSSelector::kMatchLink);
2952
2953 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
2954 cascade.Apply();
2955
2956 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("outline-color"));
2957
2958 Color red(255, 0, 0);
2959 const CSSProperty& outline_color = GetCSSPropertyOutlineColor();
2960 EXPECT_EQ(red, cascade.TakeStyle()->VisitedDependentColor(outline_color));
2961 }
2962
TEST_F(StyleCascadeTest,ApplyWithFilter)2963 TEST_F(StyleCascadeTest, ApplyWithFilter) {
2964 TestCascade cascade(GetDocument());
2965 cascade.Add("color", "blue", Origin::kAuthor);
2966 cascade.Add("background-color", "green", Origin::kAuthor);
2967 cascade.Add("display", "inline", Origin::kAuthor);
2968 cascade.Apply();
2969
2970 cascade.Reset();
2971 cascade.Add("color", "green", Origin::kAuthor);
2972 cascade.Add("background-color", "red", Origin::kAuthor);
2973 cascade.Add("display", "block", Origin::kAuthor);
2974 cascade.Apply(CascadeFilter(CSSProperty::kInherited, false));
2975 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2976 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("background-color"));
2977 EXPECT_EQ("inline", cascade.ComputedValue("display"));
2978 }
2979
TEST_F(StyleCascadeTest,HasAuthorBackground)2980 TEST_F(StyleCascadeTest, HasAuthorBackground) {
2981 Vector<String> properties = {"background-attachment", "background-blend-mode",
2982 "background-clip", "background-image",
2983 "background-origin", "background-position-x",
2984 "background-position-y", "background-size"};
2985
2986 for (String property : properties) {
2987 TestCascade cascade(GetDocument());
2988 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
2989 cascade.Add(property, "unset", Origin::kAuthor);
2990 cascade.Apply();
2991 EXPECT_TRUE(cascade.TakeStyle()->HasAuthorBackground());
2992 }
2993 }
2994
TEST_F(StyleCascadeTest,HasAuthorBorder)2995 TEST_F(StyleCascadeTest, HasAuthorBorder) {
2996 Vector<String> properties = {
2997 "border-top-color", "border-right-color",
2998 "border-bottom-color", "border-left-color",
2999 "border-top-style", "border-right-style",
3000 "border-bottom-style", "border-left-style",
3001 "border-top-width", "border-right-width",
3002 "border-bottom-width", "border-left-width",
3003 "border-top-left-radius", "border-top-right-radius",
3004 "border-bottom-left-radius", "border-bottom-right-radius",
3005 "border-image-source", "border-image-slice",
3006 "border-image-width", "border-image-outset",
3007 "border-image-repeat"};
3008
3009 for (String property : properties) {
3010 TestCascade cascade(GetDocument());
3011 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3012 cascade.Add(property, "unset", Origin::kAuthor);
3013 cascade.Apply();
3014 EXPECT_TRUE(cascade.TakeStyle()->HasAuthorBorder());
3015 }
3016 }
3017
TEST_F(StyleCascadeTest,HasAuthorBorderLogical)3018 TEST_F(StyleCascadeTest, HasAuthorBorderLogical) {
3019 TestCascade cascade(GetDocument());
3020 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3021 cascade.Add("border-block-start-color", "red", Origin::kUserAgent);
3022 cascade.Add("border-block-start-color", "green", Origin::kAuthor);
3023 cascade.Apply();
3024 auto style = cascade.TakeStyle();
3025 EXPECT_TRUE(style->HasAuthorBorder());
3026 }
3027
TEST_F(StyleCascadeTest,NoAuthorBackgroundOrBorder)3028 TEST_F(StyleCascadeTest, NoAuthorBackgroundOrBorder) {
3029 TestCascade cascade(GetDocument());
3030 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3031 cascade.Add("background-color", "red", Origin::kUserAgent);
3032 cascade.Add("border-left-color", "green", Origin::kUserAgent);
3033 cascade.Add("background-clip", "padding-box", Origin::kUser);
3034 cascade.Add("border-right-color", "green", Origin::kUser);
3035 cascade.Apply();
3036 auto style = cascade.TakeStyle();
3037 EXPECT_FALSE(style->HasAuthorBackground());
3038 EXPECT_FALSE(style->HasAuthorBorder());
3039 }
3040
TEST_F(StyleCascadeTest,AuthorBackgroundRevert)3041 TEST_F(StyleCascadeTest, AuthorBackgroundRevert) {
3042 TestCascade cascade(GetDocument());
3043 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3044 cascade.Add("background-color", "red", Origin::kUserAgent);
3045 cascade.Add("background-color", "revert", Origin::kAuthor);
3046 cascade.Apply();
3047 auto style = cascade.TakeStyle();
3048 EXPECT_FALSE(style->HasAuthorBackground());
3049 }
3050
TEST_F(StyleCascadeTest,AuthorBorderRevert)3051 TEST_F(StyleCascadeTest, AuthorBorderRevert) {
3052 TestCascade cascade(GetDocument());
3053 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3054 cascade.Add("border-top-color", "red", Origin::kUserAgent);
3055 cascade.Add("border-top-color", "revert", Origin::kAuthor);
3056 cascade.Apply();
3057 auto style = cascade.TakeStyle();
3058 EXPECT_FALSE(style->HasAuthorBorder());
3059 }
3060
TEST_F(StyleCascadeTest,AuthorBorderRevertLogical)3061 TEST_F(StyleCascadeTest, AuthorBorderRevertLogical) {
3062 TestCascade cascade(GetDocument());
3063 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
3064 cascade.Add("border-block-start-color", "red", Origin::kUserAgent);
3065 cascade.Add("border-block-start-color", "revert", Origin::kAuthor);
3066 cascade.Apply();
3067 auto style = cascade.TakeStyle();
3068 EXPECT_FALSE(style->HasAuthorBorder());
3069 }
3070
TEST_F(StyleCascadeTest,AnalyzeMatchResult)3071 TEST_F(StyleCascadeTest, AnalyzeMatchResult) {
3072 auto ua = CascadeOrigin::kUserAgent;
3073 auto author = CascadeOrigin::kAuthor;
3074
3075 TestCascade cascade(GetDocument());
3076 cascade.Add("display:none;left:5px", ua);
3077 cascade.Add("font-size:1px !important", ua);
3078 cascade.Add("display:block;color:red", author);
3079 cascade.Add("font-size:3px", author);
3080 cascade.Apply();
3081
3082 EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author);
3083 EXPECT_EQ(cascade.GetPriority("left").GetOrigin(), ua);
3084 EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), author);
3085 EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), ua);
3086 }
3087
TEST_F(StyleCascadeTest,AnalyzeMatchResultAll)3088 TEST_F(StyleCascadeTest, AnalyzeMatchResultAll) {
3089 auto ua = CascadeOrigin::kUserAgent;
3090 auto author = CascadeOrigin::kAuthor;
3091
3092 TestCascade cascade(GetDocument());
3093 cascade.Add("display:block", ua);
3094 cascade.Add("font-size:1px !important", ua);
3095 cascade.Add("all:unset", author);
3096 cascade.Apply();
3097
3098 EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author);
3099 EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), ua);
3100
3101 // Random sample from another property affected by 'all'.
3102 EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), author);
3103 EXPECT_EQ(cascade.GetPriority("color"), cascade.GetPriority("display"));
3104 }
3105
TEST_F(StyleCascadeTest,AnalyzeFlagsClean)3106 TEST_F(StyleCascadeTest, AnalyzeFlagsClean) {
3107 AppendSheet(R"HTML(
3108 @keyframes test {
3109 from { top: 0px; }
3110 to { top: 10px; }
3111 }
3112 )HTML");
3113
3114 TestCascade cascade(GetDocument());
3115
3116 cascade.Add("bottom:10px");
3117 cascade.Add("animation:test linear 1000s -500s");
3118 cascade.Apply();
3119 EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
3120 EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
3121
3122 cascade.CalculateAnimationUpdate();
3123 cascade.Apply();
3124 EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
3125 EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
3126 }
3127
TEST_F(StyleCascadeTest,ApplyMatchResultFilter)3128 TEST_F(StyleCascadeTest, ApplyMatchResultFilter) {
3129 TestCascade cascade(GetDocument());
3130 cascade.Add("display:block");
3131 cascade.Add("color:green");
3132 cascade.Add("font-size:3px");
3133 cascade.Apply();
3134
3135 cascade.Reset();
3136 cascade.Add("display:inline");
3137 cascade.Add("color:red");
3138 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
3139
3140 EXPECT_EQ("inline", cascade.ComputedValue("display"));
3141 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
3142 EXPECT_EQ("3px", cascade.ComputedValue("font-size"));
3143 }
3144
TEST_F(StyleCascadeTest,ApplyMatchResultAllFilter)3145 TEST_F(StyleCascadeTest, ApplyMatchResultAllFilter) {
3146 TestCascade cascade(GetDocument());
3147 cascade.Add("color:green");
3148 cascade.Add("display:block");
3149 cascade.Apply();
3150
3151 cascade.Reset();
3152 cascade.Add("all:unset");
3153 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
3154
3155 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
3156 EXPECT_EQ("inline", cascade.ComputedValue("display"));
3157 }
3158
TEST_F(StyleCascadeTest,MarkHasReferenceLonghand)3159 TEST_F(StyleCascadeTest, MarkHasReferenceLonghand) {
3160 TestCascade cascade(GetDocument());
3161
3162 cascade.Add("--x:red");
3163 cascade.Add("background-color:var(--x)");
3164 cascade.Apply();
3165
3166 EXPECT_TRUE(cascade.State()
3167 .StyleRef()
3168 .HasVariableReferenceFromNonInheritedProperty());
3169 }
3170
TEST_F(StyleCascadeTest,MarkHasReferenceShorthand)3171 TEST_F(StyleCascadeTest, MarkHasReferenceShorthand) {
3172 TestCascade cascade(GetDocument());
3173
3174 cascade.Add("--x:red");
3175 cascade.Add("background:var(--x)");
3176 cascade.Apply();
3177
3178 EXPECT_TRUE(cascade.State()
3179 .StyleRef()
3180 .HasVariableReferenceFromNonInheritedProperty());
3181 }
3182
TEST_F(StyleCascadeTest,NoMarkHasReferenceForInherited)3183 TEST_F(StyleCascadeTest, NoMarkHasReferenceForInherited) {
3184 TestCascade cascade(GetDocument());
3185
3186 cascade.Add("--x:red");
3187 cascade.Add("--y:caption");
3188 cascade.Add("color:var(--x)");
3189 cascade.Add("font:var(--y)");
3190 cascade.Apply();
3191
3192 EXPECT_FALSE(cascade.State()
3193 .StyleRef()
3194 .HasVariableReferenceFromNonInheritedProperty());
3195 }
3196
TEST_F(StyleCascadeTest,Reset)3197 TEST_F(StyleCascadeTest, Reset) {
3198 TestCascade cascade(GetDocument());
3199
3200 EXPECT_EQ(CascadePriority(), cascade.GetPriority("color"));
3201 EXPECT_EQ(CascadePriority(), cascade.GetPriority("--x"));
3202
3203 cascade.Add("color:red");
3204 cascade.Add("--x:red");
3205 cascade.Apply(); // generation=1
3206 cascade.Apply(); // generation=2
3207
3208 EXPECT_EQ(2u, cascade.GetPriority("color").GetGeneration());
3209 EXPECT_EQ(2u, cascade.GetPriority("--x").GetGeneration());
3210
3211 cascade.Reset();
3212
3213 EXPECT_EQ(CascadePriority(), cascade.GetPriority("color"));
3214 EXPECT_EQ(CascadePriority(), cascade.GetPriority("--x"));
3215 }
3216
TEST_F(StyleCascadeTest,GetImportantSetEmpty)3217 TEST_F(StyleCascadeTest, GetImportantSetEmpty) {
3218 TestCascade cascade(GetDocument());
3219 cascade.Add("color:red");
3220 cascade.Add("width:1px");
3221 cascade.Add("--x:green");
3222 EXPECT_FALSE(cascade.GetImportantSet());
3223 }
3224
TEST_F(StyleCascadeTest,GetImportantSetSingle)3225 TEST_F(StyleCascadeTest, GetImportantSetSingle) {
3226 TestCascade cascade(GetDocument());
3227 cascade.Add("width:1px !important");
3228 ASSERT_TRUE(cascade.GetImportantSet());
3229 EXPECT_EQ(CSSBitset({CSSPropertyID::kWidth}), *cascade.GetImportantSet());
3230 }
3231
TEST_F(StyleCascadeTest,GetImportantSetMany)3232 TEST_F(StyleCascadeTest, GetImportantSetMany) {
3233 TestCascade cascade(GetDocument());
3234 cascade.Add("width:1px !important");
3235 cascade.Add("height:1px !important");
3236 cascade.Add("top:1px !important");
3237 ASSERT_TRUE(cascade.GetImportantSet());
3238 EXPECT_EQ(CSSBitset({CSSPropertyID::kWidth, CSSPropertyID::kHeight,
3239 CSSPropertyID::kTop}),
3240 *cascade.GetImportantSet());
3241 }
3242
TEST_F(StyleCascadeTest,NoDependenciesPresent)3243 TEST_F(StyleCascadeTest, NoDependenciesPresent) {
3244 TestCascade cascade(GetDocument());
3245 cascade.Add("left:2px");
3246 cascade.Add("top:initial");
3247 cascade.Add("border:1px solid black");
3248 cascade.Add("--x:bar");
3249 cascade.Add("direction:rtl");
3250 cascade.Apply();
3251 const auto& state = cascade.State();
3252 EXPECT_TRUE(state.Dependencies().IsEmpty());
3253 EXPECT_FALSE(state.HasIncomparableDependency());
3254 }
3255
TEST_F(StyleCascadeTest,ExplicitInheritanceDependencyIsDetected)3256 TEST_F(StyleCascadeTest, ExplicitInheritanceDependencyIsDetected) {
3257 TestCascade cascade(GetDocument());
3258 cascade.Add("left:inherit");
3259 cascade.Add("right:inherit");
3260 cascade.Apply();
3261 const auto& state = cascade.State();
3262 EXPECT_EQ(2u, state.Dependencies().size());
3263 EXPECT_TRUE(state.Dependencies().Contains(PropertyName("left")));
3264 EXPECT_TRUE(state.Dependencies().Contains(PropertyName("right")));
3265 EXPECT_FALSE(state.HasIncomparableDependency());
3266 }
3267
TEST_F(StyleCascadeTest,IncomparableDependencyDetected)3268 TEST_F(StyleCascadeTest, IncomparableDependencyDetected) {
3269 ASSERT_FALSE(
3270 GetCSSPropertyInternalEmptyLineHeight().IsComputedValueComparable());
3271
3272 TestCascade cascade(GetDocument());
3273 cascade.Add("-internal-empty-line-height:inherit", CascadeOrigin::kUserAgent);
3274 cascade.Apply();
3275 const auto& state = cascade.State();
3276 EXPECT_EQ(1u, state.Dependencies().size());
3277 EXPECT_TRUE(state.Dependencies().Contains(
3278 CSSPropertyName(CSSPropertyID::kInternalEmptyLineHeight)));
3279 EXPECT_TRUE(state.HasIncomparableDependency());
3280 }
3281
TEST_F(StyleCascadeTest,CustomPropertyDependencyIsDetected)3282 TEST_F(StyleCascadeTest, CustomPropertyDependencyIsDetected) {
3283 TestCascade cascade(GetDocument());
3284 cascade.Add("left:var(--x,1px)");
3285 cascade.Add("right:var(--x,2px)");
3286 cascade.Apply();
3287 const auto& state = cascade.State();
3288 EXPECT_EQ(1u, state.Dependencies().size());
3289 EXPECT_TRUE(state.Dependencies().Contains(PropertyName("--x")));
3290 EXPECT_FALSE(state.HasIncomparableDependency());
3291 }
3292
TEST_F(StyleCascadeTest,NonInheritedCustomPropertyIsNoDependency)3293 TEST_F(StyleCascadeTest, NonInheritedCustomPropertyIsNoDependency) {
3294 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
3295 TestCascade cascade(GetDocument());
3296 cascade.Add("left:var(--x,1px)");
3297 cascade.Add("right:var(--x,2px)");
3298 cascade.Apply();
3299 const auto& state = cascade.State();
3300 EXPECT_EQ(0u, state.Dependencies().size());
3301 }
3302
TEST_F(StyleCascadeTest,DirectionAndWritingModeDependenciesAreDetected)3303 TEST_F(StyleCascadeTest, DirectionAndWritingModeDependenciesAreDetected) {
3304 TestCascade cascade(GetDocument());
3305 cascade.Add("margin-inline-start: 2px");
3306 cascade.Apply();
3307 const auto& state = cascade.State();
3308 EXPECT_EQ(2u, state.Dependencies().size());
3309 EXPECT_TRUE(state.Dependencies().Contains(PropertyName("direction")));
3310 EXPECT_TRUE(state.Dependencies().Contains(PropertyName("writing-mode")));
3311 EXPECT_FALSE(state.HasIncomparableDependency());
3312 }
3313
TEST_F(StyleCascadeTest,RootColorNotModifiedByEmptyCascade)3314 TEST_F(StyleCascadeTest, RootColorNotModifiedByEmptyCascade) {
3315 TestCascade cascade(GetDocument(), GetDocument().documentElement());
3316 cascade.Add("color:red");
3317 cascade.Apply();
3318
3319 cascade.Reset();
3320 cascade.Add("display:block");
3321 cascade.Apply(); // Should not affect 'color'.
3322
3323 auto style = cascade.TakeStyle();
3324
3325 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
3326 EXPECT_EQ(Color(255, 0, 0),
3327 style->VisitedDependentColor(GetCSSPropertyColor()));
3328
3329 style->SetInsideLink(EInsideLink::kNotInsideLink);
3330 EXPECT_EQ(Color(255, 0, 0),
3331 style->VisitedDependentColor(GetCSSPropertyColor()));
3332 }
3333
TEST_F(StyleCascadeTest,InitialColor)3334 TEST_F(StyleCascadeTest, InitialColor) {
3335 ColorSchemeHelper color_scheme_helper(GetDocument());
3336 color_scheme_helper.SetPreferredColorScheme(
3337 mojom::blink::PreferredColorScheme::kDark);
3338
3339 TestCascade cascade(GetDocument(), GetDocument().documentElement());
3340 cascade.Add("color-scheme:dark");
3341
3342 // CSSInitialColorValue is not reachable via a string, hence we must
3343 // create the CSSPropertyValueSet that contains it manually.
3344 auto* set =
3345 MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
3346 set->SetProperty(CSSPropertyID::kColor, *CSSInitialColorValue::Create());
3347 cascade.Add(set);
3348
3349 cascade.Apply();
3350
3351 auto style = cascade.TakeStyle();
3352
3353 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
3354 EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor()));
3355
3356 style->SetInsideLink(EInsideLink::kNotInsideLink);
3357 EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor()));
3358 }
3359
TEST_F(StyleCascadeTest,MaxSubstitutionTokens)3360 TEST_F(StyleCascadeTest, MaxSubstitutionTokens) {
3361 StringBuilder builder;
3362 for (size_t i = 0; i < StyleCascade::kMaxSubstitutionTokens; ++i)
3363 builder.Append(':'); // <colon-token>
3364
3365 String at_limit = builder.ToString();
3366 String above_limit = builder.ToString() + ":";
3367
3368 TestCascade cascade(GetDocument());
3369 cascade.Add("--at-limit", at_limit);
3370 cascade.Add("--above-limit", above_limit);
3371 cascade.Add("--at-limit-reference", "var(--at-limit)");
3372 cascade.Add("--above-limit-reference", "var(--above-limit)");
3373 cascade.Add("--at-limit-reference-fallback",
3374 "var(--unknown,var(--at-limit))");
3375 cascade.Add("--above-limit-reference-fallback",
3376 "var(--unknown,var(--above-limit))");
3377 cascade.Apply();
3378
3379 EXPECT_EQ(at_limit, cascade.ComputedValue("--at-limit"));
3380 EXPECT_EQ(above_limit, cascade.ComputedValue("--above-limit"));
3381 EXPECT_EQ(at_limit, cascade.ComputedValue("--at-limit-reference"));
3382 EXPECT_EQ(g_null_atom, cascade.ComputedValue("--above-limit-reference"));
3383 EXPECT_EQ(at_limit, cascade.ComputedValue("--at-limit-reference-fallback"));
3384 EXPECT_EQ(g_null_atom,
3385 cascade.ComputedValue("--above-limit-reference-fallback"));
3386 }
3387
TEST_F(StyleCascadeTest,UseCountSummary)3388 TEST_F(StyleCascadeTest, UseCountSummary) {
3389 const auto feature = WebFeature::kSummaryElementWithDisplayBlockAuthorRule;
3390
3391 Element* summary = GetDocument().CreateRawElement(html_names::kSummaryTag);
3392 GetDocument().body()->AppendChild(summary);
3393
3394 {
3395 ASSERT_FALSE(GetDocument().IsUseCounted(feature));
3396
3397 TestCascade cascade(GetDocument(), summary);
3398 cascade.Apply();
3399 EXPECT_FALSE(GetDocument().IsUseCounted(feature));
3400 }
3401 {
3402 ASSERT_FALSE(GetDocument().IsUseCounted(feature));
3403
3404 TestCascade cascade(GetDocument(), summary);
3405 cascade.Add("color:green");
3406 cascade.Apply();
3407 EXPECT_FALSE(GetDocument().IsUseCounted(feature));
3408 }
3409 {
3410 ASSERT_FALSE(GetDocument().IsUseCounted(feature));
3411
3412 TestCascade cascade(GetDocument(), summary);
3413 cascade.Add("display:block", CascadeOrigin::kUserAgent);
3414 cascade.Apply();
3415 EXPECT_FALSE(GetDocument().IsUseCounted(feature));
3416 }
3417 {
3418 ASSERT_FALSE(GetDocument().IsUseCounted(feature));
3419
3420 TestCascade cascade(GetDocument(), summary);
3421 cascade.Add("display:block", CascadeOrigin::kUser);
3422 cascade.Apply();
3423 EXPECT_TRUE(GetDocument().IsUseCounted(feature));
3424 GetDocument().ClearUseCounterForTesting(feature);
3425 }
3426 {
3427 ASSERT_FALSE(GetDocument().IsUseCounted(feature));
3428
3429 TestCascade cascade(GetDocument(), summary);
3430 cascade.Add("display:block", CascadeOrigin::kAuthor);
3431 cascade.Apply();
3432 EXPECT_TRUE(GetDocument().IsUseCounted(feature));
3433 GetDocument().ClearUseCounterForTesting(feature);
3434 }
3435 }
3436
TEST_F(StyleCascadeTest,GetCascadedValues)3437 TEST_F(StyleCascadeTest, GetCascadedValues) {
3438 TestCascade cascade(GetDocument());
3439 cascade.Add("top:1px", CascadeOrigin::kUserAgent);
3440 cascade.Add("right:2px", CascadeOrigin::kUserAgent);
3441 cascade.Add("bottom:3px", CascadeOrigin::kUserAgent);
3442 cascade.Add("left:4px !important", CascadeOrigin::kUserAgent);
3443 cascade.Add("width:5px", CascadeOrigin::kUserAgent);
3444
3445 cascade.Add("top:10px", CascadeOrigin::kUser);
3446 cascade.Add("right:20px", CascadeOrigin::kUser);
3447 cascade.Add("bottom:30px !important", CascadeOrigin::kUser);
3448 cascade.Add("left:40px", CascadeOrigin::kUser);
3449 cascade.Add("height:60px", CascadeOrigin::kUser);
3450 cascade.Add("height:61px", CascadeOrigin::kUser);
3451 cascade.Add("--x:70px", CascadeOrigin::kUser);
3452 cascade.Add("--y:80px !important", CascadeOrigin::kUser);
3453
3454 cascade.Add("top:100px", CascadeOrigin::kAuthor);
3455 cascade.Add("right:201px !important", CascadeOrigin::kAuthor);
3456 cascade.Add("right:200px", CascadeOrigin::kAuthor);
3457 cascade.Add("bottom:300px", CascadeOrigin::kAuthor);
3458 cascade.Add("left:400px", CascadeOrigin::kAuthor);
3459 cascade.Add("--x:700px", CascadeOrigin::kAuthor);
3460 cascade.Add("--y:800px", CascadeOrigin::kAuthor);
3461
3462 cascade.Apply();
3463
3464 auto map = cascade.GetCascadedValues();
3465 EXPECT_EQ(8u, map.size());
3466
3467 EXPECT_EQ("100px", CssTextAt(map, "top"));
3468 EXPECT_EQ("201px", CssTextAt(map, "right"));
3469 EXPECT_EQ("30px", CssTextAt(map, "bottom"));
3470 EXPECT_EQ("4px", CssTextAt(map, "left"));
3471 EXPECT_EQ("5px", CssTextAt(map, "width"));
3472 EXPECT_EQ("61px", CssTextAt(map, "height"));
3473 EXPECT_EQ("700px", CssTextAt(map, "--x"));
3474 EXPECT_EQ("80px ", CssTextAt(map, "--y"));
3475 }
3476
TEST_F(StyleCascadeTest,GetCascadedValuesCssWide)3477 TEST_F(StyleCascadeTest, GetCascadedValuesCssWide) {
3478 TestCascade cascade(GetDocument());
3479 cascade.Add("top:initial");
3480 cascade.Add("right:inherit");
3481 cascade.Add("bottom:unset");
3482 cascade.Add("left:revert");
3483 cascade.Apply();
3484
3485 auto map = cascade.GetCascadedValues();
3486 EXPECT_EQ(4u, map.size());
3487
3488 EXPECT_EQ("initial", CssTextAt(map, "top"));
3489 EXPECT_EQ("inherit", CssTextAt(map, "right"));
3490 EXPECT_EQ("unset", CssTextAt(map, "bottom"));
3491 EXPECT_EQ("revert", CssTextAt(map, "left"));
3492 }
3493
TEST_F(StyleCascadeTest,GetCascadedValuesLogical)3494 TEST_F(StyleCascadeTest, GetCascadedValuesLogical) {
3495 TestCascade cascade(GetDocument());
3496 cascade.Add("margin-inline-start:1px");
3497 cascade.Add("margin-inline-end:2px");
3498 cascade.Apply();
3499
3500 auto map = cascade.GetCascadedValues();
3501 EXPECT_EQ(2u, map.size());
3502
3503 EXPECT_EQ("1px", CssTextAt(map, "margin-left"));
3504 EXPECT_EQ("2px", CssTextAt(map, "margin-right"));
3505 }
3506
TEST_F(StyleCascadeTest,GetCascadedValuesInterpolated)3507 TEST_F(StyleCascadeTest, GetCascadedValuesInterpolated) {
3508 AppendSheet(R"HTML(
3509 @keyframes test {
3510 from { --x: 100px; width: 100px; }
3511 to { --x: 200px; width: 200px; }
3512 }
3513 )HTML");
3514
3515 TestCascade cascade(GetDocument());
3516
3517 cascade.Add("animation-name: test");
3518 cascade.Add("animation-timing-function: linear");
3519 cascade.Add("animation-duration: 10s");
3520 cascade.Add("animation-delay: -5s");
3521 cascade.Apply();
3522
3523 cascade.CalculateAnimationUpdate();
3524 cascade.Apply();
3525
3526 // Verify that effect values from the animation did apply:
3527 EXPECT_EQ(" 200px", cascade.ComputedValue("--x"));
3528 EXPECT_EQ("150px", cascade.ComputedValue("width"));
3529
3530 // However, we don't currently support returning interpolated vales from
3531 // GetCascadedValues:
3532 auto map = cascade.GetCascadedValues();
3533 EXPECT_EQ(4u, map.size());
3534
3535 EXPECT_EQ("test", CssTextAt(map, "animation-name"));
3536 EXPECT_EQ("linear", CssTextAt(map, "animation-timing-function"));
3537 EXPECT_EQ("10s", CssTextAt(map, "animation-duration"));
3538 EXPECT_EQ("-5s", CssTextAt(map, "animation-delay"));
3539 }
3540
TEST_F(StyleCascadeTest,ForcedVisitedBackgroundColor)3541 TEST_F(StyleCascadeTest, ForcedVisitedBackgroundColor) {
3542 ScopedForcedColorsForTest scoped_feature(true);
3543 ColorSchemeHelper color_scheme_helper(GetDocument());
3544 color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive);
3545 UpdateAllLifecyclePhasesForTest();
3546
3547 TestCascade cascade(GetDocument());
3548 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
3549 cascade.Add(ParseDeclarationBlock("background-color:#aabbccdd"),
3550 CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
3551 cascade.Apply();
3552
3553 Color forced_bg_color =
3554 StyleColor(CSSValueID::kCanvas)
3555 .Resolve(Color(), mojom::blink::ColorScheme::kLight);
3556 Color expected_bg_color =
3557 Color(forced_bg_color.Red(), forced_bg_color.Green(),
3558 forced_bg_color.Blue(), 0xdd);
3559
3560 // Verify that the visited background color alpha channel is preserved in
3561 // Forced Colors Mode.
3562 EXPECT_EQ(
3563 expected_bg_color,
3564 cascade.State().Style()->InternalVisitedBackgroundColor().GetColor());
3565 }
3566
TEST_F(StyleCascadeTest,RevertOrigin)3567 TEST_F(StyleCascadeTest, RevertOrigin) {
3568 TestCascade cascade(GetDocument());
3569
3570 cascade.Add("width", "1px", CascadeOrigin::kUserAgent);
3571 cascade.Add("height", "1px", CascadeOrigin::kUserAgent);
3572 cascade.Add("display", "block", CascadeOrigin::kUserAgent);
3573 cascade.Add("width", "2px", CascadeOrigin::kUser);
3574 cascade.Add("height", "revert", CascadeOrigin::kUser);
3575 cascade.Add("width", "revert", CascadeOrigin::kAuthor);
3576 cascade.Add("height", "revert", CascadeOrigin::kAuthor);
3577 cascade.Add("display", "revert", CascadeOrigin::kAuthor);
3578 cascade.Add("margin-left", "revert", CascadeOrigin::kAuthor);
3579
3580 cascade.AnalyzeIfNeeded();
3581
3582 CSSValue* revert_value = cssvalue::CSSRevertValue::Create();
3583
3584 TestCascadeResolver resolver;
3585
3586 CascadeOrigin origin = CascadeOrigin::kAuthor;
3587 const CSSValue* resolved_value =
3588 cascade.Resolve(GetCSSPropertyWidth(), *revert_value, origin);
3589 ASSERT_TRUE(resolved_value);
3590 EXPECT_EQ(CascadeOrigin::kUser, origin);
3591 EXPECT_EQ("2px", resolved_value->CssText());
3592
3593 origin = CascadeOrigin::kAuthor;
3594 resolved_value =
3595 cascade.Resolve(GetCSSPropertyHeight(), *revert_value, origin);
3596 ASSERT_TRUE(resolved_value);
3597 EXPECT_EQ(CascadeOrigin::kUserAgent, origin);
3598 EXPECT_EQ("1px", resolved_value->CssText());
3599
3600 origin = CascadeOrigin::kAuthor;
3601 resolved_value =
3602 cascade.Resolve(GetCSSPropertyDisplay(), *revert_value, origin);
3603 ASSERT_TRUE(resolved_value);
3604 EXPECT_EQ(CascadeOrigin::kUserAgent, origin);
3605 EXPECT_EQ("block", resolved_value->CssText());
3606
3607 origin = CascadeOrigin::kAuthor;
3608 resolved_value =
3609 cascade.Resolve(GetCSSPropertyMarginLeft(), *revert_value, origin);
3610 ASSERT_TRUE(resolved_value);
3611 EXPECT_EQ(CascadeOrigin::kNone, origin);
3612 EXPECT_EQ("unset", resolved_value->CssText());
3613 }
3614
3615 } // namespace blink
3616