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_pending_substitution_value.h"
14 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
15 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
16 #include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
17 #include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
18 #include "third_party/blink/renderer/core/css/media_query_evaluator.h"
19 #include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
20 #include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
21 #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
22 #include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
23 #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
24 #include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
25 #include "third_party/blink/renderer/core/css/properties/css_property_instances.h"
26 #include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
27 #include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
28 #include "third_party/blink/renderer/core/css/property_registry.h"
29 #include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
30 #include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h"
31 #include "third_party/blink/renderer/core/css/resolver/cascade_map.h"
32 #include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
33 #include "third_party/blink/renderer/core/css/resolver/cascade_resolver.h"
34 #include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h"
35 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
36 #include "third_party/blink/renderer/core/css/style_engine.h"
37 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
38 #include "third_party/blink/renderer/core/html/html_element.h"
39 #include "third_party/blink/renderer/core/style/computed_style.h"
40 #include "third_party/blink/renderer/core/style_property_shorthand.h"
41 #include "third_party/blink/renderer/core/testing/page_test_base.h"
42 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
43 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
44
45 namespace blink {
46
47 using css_test_helpers::ParseDeclarationBlock;
48 using css_test_helpers::RegisterProperty;
49 using Origin = CascadeOrigin;
50 using Priority = CascadePriority;
51 using UnitType = CSSPrimitiveValue::UnitType;
52
53 class TestCascade {
54 STACK_ALLOCATED();
55
56 public:
TestCascade(Document & document,Element * target=nullptr)57 TestCascade(Document& document, Element* target = nullptr)
58 : state_(document, target ? *target : *document.body()),
59 cascade_(InitState(state_)) {}
60
TakeStyle()61 scoped_refptr<ComputedStyle> TakeStyle() { return state_.TakeStyle(); }
62
State()63 StyleResolverState& State() { return state_; }
InnerCascade()64 StyleCascade& InnerCascade() { return cascade_; }
65
InheritFrom(scoped_refptr<ComputedStyle> parent)66 void InheritFrom(scoped_refptr<ComputedStyle> parent) {
67 state_.SetParentStyle(parent);
68 state_.StyleRef().InheritFrom(*parent);
69 }
70
71 // Note that because of how MatchResult works, declarations must be added
72 // in "origin order", i.e. UserAgent first, then User, then Author.
73
Add(String block,CascadeOrigin origin=CascadeOrigin::kAuthor,unsigned link_match_type=CSSSelector::kMatchAll)74 void Add(String block,
75 CascadeOrigin origin = CascadeOrigin::kAuthor,
76 unsigned link_match_type = CSSSelector::kMatchAll) {
77 CSSParserMode mode =
78 origin == CascadeOrigin::kUserAgent ? kUASheetMode : kHTMLStandardMode;
79 Add(ParseDeclarationBlock(block, mode), origin, link_match_type);
80 }
81
Add(String name,String value,CascadeOrigin origin=Origin::kAuthor)82 void Add(String name, String value, CascadeOrigin origin = Origin::kAuthor) {
83 Add(name + ":" + value, origin);
84 }
85
Add(const CSSPropertyValueSet * set,CascadeOrigin origin=CascadeOrigin::kAuthor,unsigned link_match_type=CSSSelector::kMatchAll)86 void Add(const CSSPropertyValueSet* set,
87 CascadeOrigin origin = CascadeOrigin::kAuthor,
88 unsigned link_match_type = CSSSelector::kMatchAll) {
89 DCHECK_LE(origin, CascadeOrigin::kAuthor) << "Animations not supported";
90 DCHECK_LE(current_origin_, origin) << "Please add declarations in order";
91 EnsureAtLeast(origin);
92 cascade_.MutableMatchResult().AddMatchedProperties(set, link_match_type);
93 }
94
Apply(CascadeFilter filter=CascadeFilter ())95 void Apply(CascadeFilter filter = CascadeFilter()) {
96 EnsureAtLeast(CascadeOrigin::kAuthor);
97 cascade_.Apply(filter);
98 }
99
ComputedValue(String name) const100 String ComputedValue(String name) const {
101 CSSPropertyRef ref(name, GetDocument());
102 DCHECK(ref.IsValid());
103 const LayoutObject* layout_object = nullptr;
104 bool allow_visited_style = false;
105 const CSSValue* value = ref.GetProperty().CSSValueFromComputedStyle(
106 *state_.Style(), layout_object, allow_visited_style);
107 return value ? value->CssText() : g_null_atom;
108 }
109
GetPriority(String name)110 CascadePriority GetPriority(String name) {
111 return GetPriority(
112 *CSSPropertyName::From(GetDocument().GetExecutionContext(), name));
113 }
114
GetPriority(CSSPropertyName name)115 CascadePriority GetPriority(CSSPropertyName name) {
116 CascadePriority* c = cascade_.map_.Find(name);
117 return c ? *c : CascadePriority();
118 }
119
GetOrigin(String name)120 CascadeOrigin GetOrigin(String name) { return GetPriority(name).GetOrigin(); }
121
CalculateTransitionUpdate()122 void CalculateTransitionUpdate() {
123 CSSAnimations::CalculateTransitionUpdate(
124 state_.AnimationUpdate(), CSSAnimations::PropertyPass::kCustom,
125 &state_.GetElement(), *state_.Style());
126 CSSAnimations::CalculateTransitionUpdate(
127 state_.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard,
128 &state_.GetElement(), *state_.Style());
129 AddTransitions();
130 }
131
CalculateAnimationUpdate()132 void CalculateAnimationUpdate() {
133 CSSAnimations::CalculateAnimationUpdate(
134 state_.AnimationUpdate(), &state_.GetElement(), state_.GetElement(),
135 *state_.Style(), state_.ParentStyle(),
136 &GetDocument().EnsureStyleResolver());
137 AddAnimations();
138 }
139
Reset()140 void Reset() { cascade_.Reset(); }
141
142 private:
GetDocument() const143 Document& GetDocument() const { return state_.GetDocument(); }
Body() const144 Element* Body() const { return GetDocument().body(); }
145
InitState(StyleResolverState & state)146 static StyleResolverState& InitState(StyleResolverState& state) {
147 state.SetStyle(InitialStyle(state.GetDocument()));
148 state.SetParentStyle(InitialStyle(state.GetDocument()));
149 return state;
150 }
151
InitialStyle(Document & document)152 static scoped_refptr<ComputedStyle> InitialStyle(Document& document) {
153 return StyleResolver::InitialStyleForElement(document);
154 }
155
FinishOrigin()156 void FinishOrigin() {
157 switch (current_origin_) {
158 case CascadeOrigin::kUserAgent:
159 cascade_.MutableMatchResult().FinishAddingUARules();
160 current_origin_ = CascadeOrigin::kUser;
161 break;
162 case CascadeOrigin::kUser:
163 cascade_.MutableMatchResult().FinishAddingUserRules();
164 current_origin_ = CascadeOrigin::kAuthor;
165 break;
166 case CascadeOrigin::kAuthor:
167 default:
168 NOTREACHED();
169 break;
170 }
171 }
172
EnsureAtLeast(CascadeOrigin origin)173 void EnsureAtLeast(CascadeOrigin origin) {
174 while (current_origin_ < origin)
175 FinishOrigin();
176 }
177
AddAnimations()178 void AddAnimations() {
179 const auto& update = state_.AnimationUpdate();
180 if (update.IsEmpty())
181 return;
182 cascade_.AddInterpolations(
183 &update.ActiveInterpolationsForCustomAnimations(),
184 CascadeOrigin::kAnimation);
185 cascade_.AddInterpolations(
186 &update.ActiveInterpolationsForStandardAnimations(),
187 CascadeOrigin::kAnimation);
188 }
189
AddTransitions()190 void AddTransitions() {
191 const auto& update = state_.AnimationUpdate();
192 if (update.IsEmpty())
193 return;
194 cascade_.AddInterpolations(
195 &update.ActiveInterpolationsForCustomTransitions(),
196 CascadeOrigin::kTransition);
197 cascade_.AddInterpolations(
198 &update.ActiveInterpolationsForStandardTransitions(),
199 CascadeOrigin::kTransition);
200 }
201
202 CascadeOrigin current_origin_ = CascadeOrigin::kUserAgent;
203 StyleResolverState state_;
204 StyleCascade cascade_;
205 };
206
207 class TestCascadeResolver {
208 STACK_ALLOCATED();
209
210 public:
TestCascadeResolver(Document & document,uint8_t generation=0)211 explicit TestCascadeResolver(Document& document, uint8_t generation = 0)
212 : document_(document), resolver_(CascadeFilter(), generation) {}
InCycle() const213 bool InCycle() const { return resolver_.InCycle(); }
DetectCycle(String name)214 bool DetectCycle(String name) {
215 CSSPropertyRef ref(name, document_);
216 DCHECK(ref.IsValid());
217 const CSSProperty& property = ref.GetProperty();
218 return resolver_.DetectCycle(property);
219 }
CycleDepth() const220 wtf_size_t CycleDepth() const { return resolver_.cycle_depth_; }
MarkApplied(CascadePriority * priority)221 void MarkApplied(CascadePriority* priority) {
222 resolver_.MarkApplied(priority);
223 }
MarkUnapplied(CascadePriority * priority)224 void MarkUnapplied(CascadePriority* priority) {
225 resolver_.MarkUnapplied(priority);
226 }
GetGeneration()227 uint8_t GetGeneration() { return resolver_.generation_; }
228
229 private:
230 friend class TestCascadeAutoLock;
231
232 Document& document_;
233 CascadeResolver resolver_;
234 };
235
236 class TestCascadeAutoLock {
237 STACK_ALLOCATED();
238
239 public:
TestCascadeAutoLock(const CSSPropertyName & name,TestCascadeResolver & resolver)240 TestCascadeAutoLock(const CSSPropertyName& name,
241 TestCascadeResolver& resolver)
242 : lock_(name, resolver.resolver_) {}
243
244 private:
245 CascadeResolver::AutoLock lock_;
246 };
247
248 class StyleCascadeTest : public PageTestBase, private ScopedCSSCascadeForTest {
249 public:
StyleCascadeTest()250 StyleCascadeTest() : ScopedCSSCascadeForTest(true) {}
251
CreateSheet(const String & css_text)252 CSSStyleSheet* CreateSheet(const String& css_text) {
253 auto* init = MakeGarbageCollected<CSSStyleSheetInit>();
254 DummyExceptionStateForTesting exception_state;
255 CSSStyleSheet* sheet =
256 CSSStyleSheet::Create(GetDocument(), init, exception_state);
257 sheet->replaceSync(css_text, exception_state);
258 sheet->Contents()->EnsureRuleSet(MediaQueryEvaluator(),
259 kRuleHasNoSpecialState);
260 return sheet;
261 }
262
AppendSheet(const String & css_text)263 void AppendSheet(const String& css_text) {
264 CSSStyleSheet* sheet = CreateSheet(css_text);
265 ASSERT_TRUE(sheet);
266
267 Element* body = GetDocument().body();
268 ASSERT_TRUE(body->IsInTreeScope());
269 TreeScope& tree_scope = body->GetTreeScope();
270 ScopedStyleResolver& scoped_resolver =
271 tree_scope.EnsureScopedStyleResolver();
272 ActiveStyleSheetVector active_sheets;
273 active_sheets.push_back(
274 std::make_pair(sheet, &sheet->Contents()->GetRuleSet()));
275 scoped_resolver.AppendActiveStyleSheets(0, active_sheets);
276 }
277
DocumentElement() const278 Element* DocumentElement() const { return GetDocument().documentElement(); }
279
SetRootFont(String value)280 void SetRootFont(String value) {
281 DocumentElement()->SetInlineStyleProperty(CSSPropertyID::kFontSize, value);
282 UpdateAllLifecyclePhasesForTest();
283 }
284
AnimationTaintedSet(AtomicString name,String value)285 const MutableCSSPropertyValueSet* AnimationTaintedSet(AtomicString name,
286 String value) {
287 CSSParserMode mode = kHTMLStandardMode;
288 auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>(mode);
289 set->SetProperty(name, value, /* important */ false,
290 SecureContextMode::kSecureContext,
291 /* context_style_sheet */ nullptr,
292 /* is_animation_tainted */ true);
293 return set;
294 }
295
296 // Temporarily create a CSS Environment Variable.
297 // https://drafts.csswg.org/css-env-1/
298 class AutoEnv {
299 STACK_ALLOCATED();
300
301 public:
AutoEnv(PageTestBase & test,AtomicString name,String value)302 AutoEnv(PageTestBase& test, AtomicString name, String value)
303 : document_(&test.GetDocument()), name_(name) {
304 EnsureEnvironmentVariables().SetVariable(name, value);
305 }
~AutoEnv()306 ~AutoEnv() { EnsureEnvironmentVariables().RemoveVariable(name_); }
307
308 private:
EnsureEnvironmentVariables()309 DocumentStyleEnvironmentVariables& EnsureEnvironmentVariables() {
310 return document_->GetStyleEngine().EnsureEnvironmentVariables();
311 }
312
313 Document* document_;
314 AtomicString name_;
315 };
316 };
317
TEST_F(StyleCascadeTest,ApplySingle)318 TEST_F(StyleCascadeTest, ApplySingle) {
319 TestCascade cascade(GetDocument());
320 cascade.Add("width", "1px", CascadeOrigin::kUserAgent);
321 cascade.Add("width", "2px", CascadeOrigin::kAuthor);
322 cascade.Apply();
323
324 EXPECT_EQ("2px", cascade.ComputedValue("width"));
325 }
326
TEST_F(StyleCascadeTest,ApplyImportance)327 TEST_F(StyleCascadeTest, ApplyImportance) {
328 TestCascade cascade(GetDocument());
329 cascade.Add("width:1px !important", CascadeOrigin::kUserAgent);
330 cascade.Add("width:2px", CascadeOrigin::kAuthor);
331 cascade.Apply();
332
333 EXPECT_EQ("1px", cascade.ComputedValue("width"));
334 }
335
TEST_F(StyleCascadeTest,ApplyAll)336 TEST_F(StyleCascadeTest, ApplyAll) {
337 TestCascade cascade(GetDocument());
338 cascade.Add("width:1px", CascadeOrigin::kUserAgent);
339 cascade.Add("height:1px", CascadeOrigin::kUserAgent);
340 cascade.Add("all:initial", CascadeOrigin::kAuthor);
341 cascade.Apply();
342
343 EXPECT_EQ("auto", cascade.ComputedValue("width"));
344 EXPECT_EQ("auto", cascade.ComputedValue("height"));
345 }
346
TEST_F(StyleCascadeTest,ApplyAllImportance)347 TEST_F(StyleCascadeTest, ApplyAllImportance) {
348 TestCascade cascade(GetDocument());
349 cascade.Add("opacity:0.5", CascadeOrigin::kUserAgent);
350 cascade.Add("display:block !important", CascadeOrigin::kUserAgent);
351 cascade.Add("all:initial", CascadeOrigin::kAuthor);
352 cascade.Apply();
353
354 EXPECT_EQ("1", cascade.ComputedValue("opacity"));
355 EXPECT_EQ("block", cascade.ComputedValue("display"));
356 }
357
TEST_F(StyleCascadeTest,ApplyAllWithPhysicalLonghands)358 TEST_F(StyleCascadeTest, ApplyAllWithPhysicalLonghands) {
359 TestCascade cascade(GetDocument());
360 cascade.Add("width:1px", CascadeOrigin::kUserAgent);
361 cascade.Add("height:1px !important", CascadeOrigin::kUserAgent);
362 cascade.Add("all:initial", CascadeOrigin::kAuthor);
363 cascade.Apply();
364 EXPECT_EQ("auto", cascade.ComputedValue("width"));
365 EXPECT_EQ("1px", cascade.ComputedValue("height"));
366 }
367
TEST_F(StyleCascadeTest,ApplyCustomProperty)368 TEST_F(StyleCascadeTest, ApplyCustomProperty) {
369 TestCascade cascade(GetDocument());
370 cascade.Add("--x", " 10px ");
371 cascade.Add("--y", "nope");
372 cascade.Apply();
373
374 EXPECT_EQ(" 10px ", cascade.ComputedValue("--x"));
375 EXPECT_EQ("nope", cascade.ComputedValue("--y"));
376 }
377
TEST_F(StyleCascadeTest,ApplyGenerations)378 TEST_F(StyleCascadeTest, ApplyGenerations) {
379 TestCascade cascade(GetDocument());
380
381 cascade.Add("--x:10px");
382 cascade.Add("width:20px");
383 cascade.Apply();
384 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
385 EXPECT_EQ("20px", cascade.ComputedValue("width"));
386
387 cascade.State().StyleRef().SetWidth(Length::Auto());
388 cascade.State().StyleRef().SetVariableData("--x", nullptr, true);
389 EXPECT_EQ(g_null_atom, cascade.ComputedValue("--x"));
390 EXPECT_EQ("auto", cascade.ComputedValue("width"));
391
392 // Apply again
393 cascade.Apply();
394 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
395 EXPECT_EQ("20px", cascade.ComputedValue("width"));
396 }
397
TEST_F(StyleCascadeTest,ApplyCustomPropertyVar)398 TEST_F(StyleCascadeTest, ApplyCustomPropertyVar) {
399 // Apply --x first.
400 {
401 TestCascade cascade(GetDocument());
402 cascade.Add("--x", "yes and var(--y)");
403 cascade.Add("--y", "no");
404 cascade.Apply();
405
406 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
407 EXPECT_EQ("no", cascade.ComputedValue("--y"));
408 }
409
410 // Apply --y first.
411 {
412 TestCascade cascade(GetDocument());
413 cascade.Add("--y", "no");
414 cascade.Add("--x", "yes and var(--y)");
415 cascade.Apply();
416
417 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
418 EXPECT_EQ("no", cascade.ComputedValue("--y"));
419 }
420 }
421
TEST_F(StyleCascadeTest,InvalidVarReferenceCauseInvalidVariable)422 TEST_F(StyleCascadeTest, InvalidVarReferenceCauseInvalidVariable) {
423 TestCascade cascade(GetDocument());
424 cascade.Add("--x", "nope var(--y)");
425 cascade.Apply();
426
427 EXPECT_EQ(g_null_atom, cascade.ComputedValue("--x"));
428 }
429
TEST_F(StyleCascadeTest,ApplyCustomPropertyFallback)430 TEST_F(StyleCascadeTest, ApplyCustomPropertyFallback) {
431 TestCascade cascade(GetDocument());
432 cascade.Add("--x", "yes and var(--y,no)");
433 cascade.Apply();
434
435 EXPECT_EQ("yes and no", cascade.ComputedValue("--x"));
436 }
437
TEST_F(StyleCascadeTest,RegisteredPropertyFallback)438 TEST_F(StyleCascadeTest, RegisteredPropertyFallback) {
439 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
440
441 TestCascade cascade(GetDocument());
442 cascade.Add("--x", "var(--y,10px)");
443 cascade.Apply();
444
445 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
446 }
447
TEST_F(StyleCascadeTest,RegisteredPropertyFallbackValidation)448 TEST_F(StyleCascadeTest, RegisteredPropertyFallbackValidation) {
449 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
450
451 TestCascade cascade(GetDocument());
452 cascade.Add("--x", "10px");
453 cascade.Add("--y", "var(--x,red)"); // Fallback must be valid <length>.
454 cascade.Add("--z", "var(--y,pass)");
455 cascade.Apply();
456
457 EXPECT_EQ("pass", cascade.ComputedValue("--z"));
458 }
459
TEST_F(StyleCascadeTest,VarInFallback)460 TEST_F(StyleCascadeTest, VarInFallback) {
461 TestCascade cascade(GetDocument());
462 cascade.Add("--x", "one var(--z,two var(--y))");
463 cascade.Add("--y", "three");
464 cascade.Apply();
465
466 EXPECT_EQ("one two three", cascade.ComputedValue("--x"));
467 }
468
TEST_F(StyleCascadeTest,VarReferenceInNormalProperty)469 TEST_F(StyleCascadeTest, VarReferenceInNormalProperty) {
470 TestCascade cascade(GetDocument());
471 cascade.Add("--x", "10px");
472 cascade.Add("width", "var(--x)");
473 cascade.Apply();
474
475 EXPECT_EQ("10px", cascade.ComputedValue("width"));
476 }
477
TEST_F(StyleCascadeTest,MultipleVarRefs)478 TEST_F(StyleCascadeTest, MultipleVarRefs) {
479 TestCascade cascade(GetDocument());
480 cascade.Add("--x", "var(--y) bar var(--y)");
481 cascade.Add("--y", "foo");
482 cascade.Apply();
483
484 EXPECT_EQ("foo bar foo", cascade.ComputedValue("--x"));
485 }
486
TEST_F(StyleCascadeTest,RegisteredPropertyComputedValue)487 TEST_F(StyleCascadeTest, RegisteredPropertyComputedValue) {
488 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
489
490 TestCascade cascade(GetDocument());
491 cascade.Add("--x", "1in");
492 cascade.Apply();
493
494 EXPECT_EQ("96px", cascade.ComputedValue("--x"));
495 }
496
TEST_F(StyleCascadeTest,RegisteredPropertySyntaxErrorCausesInitial)497 TEST_F(StyleCascadeTest, RegisteredPropertySyntaxErrorCausesInitial) {
498 RegisterProperty(GetDocument(), "--x", "<length>", "10px", false);
499
500 TestCascade cascade(GetDocument());
501 cascade.Add("--x", "#fefefe");
502 cascade.Add("--y", "var(--x)");
503 cascade.Apply();
504
505 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
506 EXPECT_EQ("10px", cascade.ComputedValue("--y"));
507 }
508
TEST_F(StyleCascadeTest,RegisteredPropertySubstitution)509 TEST_F(StyleCascadeTest, RegisteredPropertySubstitution) {
510 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
511
512 TestCascade cascade(GetDocument());
513 cascade.Add("--x", "1in");
514 cascade.Add("--y", "var(--x)");
515 cascade.Apply();
516
517 EXPECT_EQ("96px", cascade.ComputedValue("--y"));
518 }
519
TEST_F(StyleCascadeTest,RegisteredPropertyChain)520 TEST_F(StyleCascadeTest, RegisteredPropertyChain) {
521 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
522 RegisterProperty(GetDocument(), "--z", "<length>", "0px", false);
523
524 TestCascade cascade(GetDocument());
525 cascade.Add("--x", "1in");
526 cascade.Add("--y", "var(--x)");
527 cascade.Add("--z", "calc(var(--y) + 1in)");
528 cascade.Apply();
529
530 EXPECT_EQ("96px", cascade.ComputedValue("--x"));
531 EXPECT_EQ("96px", cascade.ComputedValue("--y"));
532 EXPECT_EQ("192px", cascade.ComputedValue("--z"));
533 }
534
TEST_F(StyleCascadeTest,BasicShorthand)535 TEST_F(StyleCascadeTest, BasicShorthand) {
536 TestCascade cascade(GetDocument());
537 cascade.Add("margin", "1px 2px 3px 4px");
538 cascade.Apply();
539
540 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
541 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
542 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
543 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
544 }
545
TEST_F(StyleCascadeTest,BasicVarShorthand)546 TEST_F(StyleCascadeTest, BasicVarShorthand) {
547 TestCascade cascade(GetDocument());
548 cascade.Add("margin", "1px var(--x) 3px 4px");
549 cascade.Add("--x", "2px");
550 cascade.Apply();
551
552 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
553 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
554 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
555 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
556 }
557
TEST_F(StyleCascadeTest,ApplyingPendingSubstitutionFirst)558 TEST_F(StyleCascadeTest, ApplyingPendingSubstitutionFirst) {
559 TestCascade cascade(GetDocument());
560 cascade.Add("margin", "1px var(--x) 3px 4px");
561 cascade.Add("--x", "2px");
562 cascade.Add("margin-right", "5px");
563 cascade.Apply();
564
565 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
566 EXPECT_EQ("5px", cascade.ComputedValue("margin-right"));
567 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
568 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
569 }
570
TEST_F(StyleCascadeTest,ApplyingPendingSubstitutionLast)571 TEST_F(StyleCascadeTest, ApplyingPendingSubstitutionLast) {
572 TestCascade cascade(GetDocument());
573 cascade.Add("margin-right", "5px");
574 cascade.Add("margin", "1px var(--x) 3px 4px");
575 cascade.Add("--x", "2px");
576 cascade.Apply();
577
578 EXPECT_EQ("1px", cascade.ComputedValue("margin-top"));
579 EXPECT_EQ("2px", cascade.ComputedValue("margin-right"));
580 EXPECT_EQ("3px", cascade.ComputedValue("margin-bottom"));
581 EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
582 }
583
TEST_F(StyleCascadeTest,ResolverDetectCycle)584 TEST_F(StyleCascadeTest, ResolverDetectCycle) {
585 TestCascade cascade(GetDocument());
586 TestCascadeResolver resolver(GetDocument());
587
588 {
589 TestCascadeAutoLock lock(CSSPropertyName("--a"), resolver);
590 EXPECT_FALSE(resolver.InCycle());
591 {
592 TestCascadeAutoLock lock(CSSPropertyName("--b"), resolver);
593 EXPECT_FALSE(resolver.InCycle());
594 {
595 TestCascadeAutoLock lock(CSSPropertyName("--c"), resolver);
596 EXPECT_FALSE(resolver.InCycle());
597
598 EXPECT_TRUE(resolver.DetectCycle("--a"));
599 EXPECT_TRUE(resolver.InCycle());
600 }
601 EXPECT_TRUE(resolver.InCycle());
602 }
603 EXPECT_TRUE(resolver.InCycle());
604 }
605 EXPECT_FALSE(resolver.InCycle());
606 }
607
TEST_F(StyleCascadeTest,ResolverDetectNoCycle)608 TEST_F(StyleCascadeTest, ResolverDetectNoCycle) {
609 TestCascade cascade(GetDocument());
610 TestCascadeResolver resolver(GetDocument());
611
612 {
613 TestCascadeAutoLock lock(CSSPropertyName("--a"), resolver);
614 EXPECT_FALSE(resolver.InCycle());
615 {
616 TestCascadeAutoLock lock(CSSPropertyName("--b"), resolver);
617 EXPECT_FALSE(resolver.InCycle());
618 {
619 TestCascadeAutoLock lock(CSSPropertyName("--c"), resolver);
620 EXPECT_FALSE(resolver.InCycle());
621
622 EXPECT_FALSE(resolver.DetectCycle("--x"));
623 EXPECT_FALSE(resolver.InCycle());
624 }
625 EXPECT_FALSE(resolver.InCycle());
626 }
627 EXPECT_FALSE(resolver.InCycle());
628 }
629 EXPECT_FALSE(resolver.InCycle());
630 }
631
TEST_F(StyleCascadeTest,ResolverDetectCycleSelf)632 TEST_F(StyleCascadeTest, ResolverDetectCycleSelf) {
633 TestCascade cascade(GetDocument());
634 TestCascadeResolver resolver(GetDocument());
635
636 {
637 TestCascadeAutoLock lock(CSSPropertyName("--a"), resolver);
638 EXPECT_FALSE(resolver.InCycle());
639
640 EXPECT_TRUE(resolver.DetectCycle("--a"));
641 EXPECT_TRUE(resolver.InCycle());
642 }
643 EXPECT_FALSE(resolver.InCycle());
644 }
645
TEST_F(StyleCascadeTest,ResolverDetectMultiCycle)646 TEST_F(StyleCascadeTest, ResolverDetectMultiCycle) {
647 using AutoLock = TestCascadeAutoLock;
648
649 TestCascade cascade(GetDocument());
650 TestCascadeResolver resolver(GetDocument());
651
652 {
653 AutoLock lock(CSSPropertyName("--a"), resolver);
654 EXPECT_FALSE(resolver.InCycle());
655 {
656 AutoLock lock(CSSPropertyName("--b"), resolver);
657 EXPECT_FALSE(resolver.InCycle());
658 {
659 AutoLock lock(CSSPropertyName("--c"), resolver);
660 EXPECT_FALSE(resolver.InCycle());
661 {
662 AutoLock lock(CSSPropertyName("--d"), resolver);
663 EXPECT_FALSE(resolver.InCycle());
664
665 // Cycle 1 (big cycle):
666 EXPECT_TRUE(resolver.DetectCycle("--b"));
667 EXPECT_TRUE(resolver.InCycle());
668 EXPECT_EQ(1u, resolver.CycleDepth());
669
670 // Cycle 2 (small cycle):
671 EXPECT_TRUE(resolver.DetectCycle("--c"));
672 EXPECT_TRUE(resolver.InCycle());
673 EXPECT_EQ(1u, resolver.CycleDepth());
674 }
675 }
676 EXPECT_TRUE(resolver.InCycle());
677 }
678 EXPECT_FALSE(resolver.InCycle());
679 }
680 EXPECT_FALSE(resolver.InCycle());
681 }
682
TEST_F(StyleCascadeTest,ResolverDetectMultiCycleReverse)683 TEST_F(StyleCascadeTest, ResolverDetectMultiCycleReverse) {
684 using AutoLock = TestCascadeAutoLock;
685
686 TestCascade cascade(GetDocument());
687 TestCascadeResolver resolver(GetDocument());
688
689 {
690 AutoLock lock(CSSPropertyName("--a"), resolver);
691 EXPECT_FALSE(resolver.InCycle());
692 {
693 AutoLock lock(CSSPropertyName("--b"), resolver);
694 EXPECT_FALSE(resolver.InCycle());
695 {
696 AutoLock lock(CSSPropertyName("--c"), resolver);
697 EXPECT_FALSE(resolver.InCycle());
698 {
699 AutoLock lock(CSSPropertyName("--d"), resolver);
700 EXPECT_FALSE(resolver.InCycle());
701
702 // Cycle 1 (small cycle):
703 EXPECT_TRUE(resolver.DetectCycle("--c"));
704 EXPECT_TRUE(resolver.InCycle());
705 EXPECT_EQ(2u, resolver.CycleDepth());
706
707 // Cycle 2 (big cycle):
708 EXPECT_TRUE(resolver.DetectCycle("--b"));
709 EXPECT_TRUE(resolver.InCycle());
710 EXPECT_EQ(1u, resolver.CycleDepth());
711 }
712 }
713 EXPECT_TRUE(resolver.InCycle());
714 }
715 EXPECT_FALSE(resolver.InCycle());
716 }
717 EXPECT_FALSE(resolver.InCycle());
718 }
719
TEST_F(StyleCascadeTest,ResolverMarkApplied)720 TEST_F(StyleCascadeTest, ResolverMarkApplied) {
721 TestCascadeResolver resolver(GetDocument(), 2);
722
723 CascadePriority priority(CascadeOrigin::kAuthor);
724 EXPECT_EQ(0, priority.GetGeneration());
725
726 resolver.MarkApplied(&priority);
727 EXPECT_EQ(2, priority.GetGeneration());
728
729 // Mark a second time to verify observation of the same generation.
730 resolver.MarkApplied(&priority);
731 EXPECT_EQ(2, priority.GetGeneration());
732 }
733
TEST_F(StyleCascadeTest,ResolverMarkUnapplied)734 TEST_F(StyleCascadeTest, ResolverMarkUnapplied) {
735 TestCascadeResolver resolver(GetDocument(), 7);
736
737 CascadePriority priority(CascadeOrigin::kAuthor);
738 EXPECT_EQ(0, priority.GetGeneration());
739
740 resolver.MarkApplied(&priority);
741 EXPECT_EQ(7, priority.GetGeneration());
742
743 resolver.MarkUnapplied(&priority);
744 EXPECT_EQ(0, priority.GetGeneration());
745
746 // Mark a second time to verify observation of the same generation.
747 resolver.MarkUnapplied(&priority);
748 EXPECT_EQ(0, priority.GetGeneration());
749 }
750
TEST_F(StyleCascadeTest,BasicCycle)751 TEST_F(StyleCascadeTest, BasicCycle) {
752 TestCascade cascade(GetDocument());
753 cascade.Add("--a", "foo");
754 cascade.Add("--b", "bar");
755 cascade.Apply();
756
757 EXPECT_EQ("foo", cascade.ComputedValue("--a"));
758 EXPECT_EQ("bar", cascade.ComputedValue("--b"));
759
760 cascade.Add("--a", "var(--b)");
761 cascade.Add("--b", "var(--a)");
762 cascade.Apply();
763
764 EXPECT_FALSE(cascade.ComputedValue("--a"));
765 EXPECT_FALSE(cascade.ComputedValue("--b"));
766 }
767
TEST_F(StyleCascadeTest,SelfCycle)768 TEST_F(StyleCascadeTest, SelfCycle) {
769 TestCascade cascade(GetDocument());
770 cascade.Add("--a", "foo");
771 cascade.Apply();
772
773 EXPECT_EQ("foo", cascade.ComputedValue("--a"));
774
775 cascade.Add("--a", "var(--a)");
776 cascade.Apply();
777
778 EXPECT_FALSE(cascade.ComputedValue("--a"));
779 }
780
TEST_F(StyleCascadeTest,SelfCycleInFallback)781 TEST_F(StyleCascadeTest, SelfCycleInFallback) {
782 TestCascade cascade(GetDocument());
783 cascade.Add("--a", "var(--x, var(--a))");
784 cascade.Apply();
785
786 EXPECT_FALSE(cascade.ComputedValue("--a"));
787 }
788
TEST_F(StyleCascadeTest,SelfCycleInUnusedFallback)789 TEST_F(StyleCascadeTest, SelfCycleInUnusedFallback) {
790 TestCascade cascade(GetDocument());
791 cascade.Add("--a", "var(--b, var(--a))");
792 cascade.Add("--b", "10px");
793 cascade.Apply();
794
795 EXPECT_FALSE(cascade.ComputedValue("--a"));
796 EXPECT_EQ("10px", cascade.ComputedValue("--b"));
797 }
798
TEST_F(StyleCascadeTest,LongCycle)799 TEST_F(StyleCascadeTest, LongCycle) {
800 TestCascade cascade(GetDocument());
801 cascade.Add("--a", "var(--b)");
802 cascade.Add("--b", "var(--c)");
803 cascade.Add("--c", "var(--d)");
804 cascade.Add("--d", "var(--e)");
805 cascade.Add("--e", "var(--a)");
806 cascade.Apply();
807
808 EXPECT_FALSE(cascade.ComputedValue("--a"));
809 EXPECT_FALSE(cascade.ComputedValue("--b"));
810 EXPECT_FALSE(cascade.ComputedValue("--c"));
811 EXPECT_FALSE(cascade.ComputedValue("--d"));
812 EXPECT_FALSE(cascade.ComputedValue("--e"));
813 }
814
TEST_F(StyleCascadeTest,PartialCycle)815 TEST_F(StyleCascadeTest, PartialCycle) {
816 TestCascade cascade(GetDocument());
817 cascade.Add("--a", "var(--b)");
818 cascade.Add("--b", "var(--a)");
819 cascade.Add("--c", "bar var(--d) var(--a)");
820 cascade.Add("--d", "foo");
821 cascade.Apply();
822
823 EXPECT_FALSE(cascade.ComputedValue("--a"));
824 EXPECT_FALSE(cascade.ComputedValue("--b"));
825 EXPECT_FALSE(cascade.ComputedValue("--c"));
826 EXPECT_EQ("foo", cascade.ComputedValue("--d"));
827 }
828
TEST_F(StyleCascadeTest,VarCycleViaFallback)829 TEST_F(StyleCascadeTest, VarCycleViaFallback) {
830 TestCascade cascade(GetDocument());
831 cascade.Add("--a", "var(--b)");
832 cascade.Add("--b", "var(--x, var(--a))");
833 cascade.Add("--c", "var(--a)");
834 cascade.Apply();
835
836 EXPECT_FALSE(cascade.ComputedValue("--a"));
837 EXPECT_FALSE(cascade.ComputedValue("--b"));
838 EXPECT_FALSE(cascade.ComputedValue("--c"));
839 }
840
TEST_F(StyleCascadeTest,FallbackTriggeredByCycle)841 TEST_F(StyleCascadeTest, FallbackTriggeredByCycle) {
842 TestCascade cascade(GetDocument());
843 cascade.Add("--a", "var(--b)");
844 cascade.Add("--b", "var(--a)");
845 cascade.Add("--c", "var(--a,foo)");
846 cascade.Apply();
847
848 EXPECT_FALSE(cascade.ComputedValue("--a"));
849 EXPECT_FALSE(cascade.ComputedValue("--b"));
850 EXPECT_EQ("foo", cascade.ComputedValue("--c"));
851 }
852
TEST_F(StyleCascadeTest,RegisteredCycle)853 TEST_F(StyleCascadeTest, RegisteredCycle) {
854 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
855 RegisterProperty(GetDocument(), "--b", "<length>", "0px", false);
856
857 TestCascade cascade(GetDocument());
858 cascade.Add("--a", "var(--b)");
859 cascade.Add("--b", "var(--a)");
860 cascade.Apply();
861
862 EXPECT_FALSE(cascade.ComputedValue("--a"));
863 EXPECT_FALSE(cascade.ComputedValue("--b"));
864 }
865
TEST_F(StyleCascadeTest,PartiallyRegisteredCycle)866 TEST_F(StyleCascadeTest, PartiallyRegisteredCycle) {
867 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
868
869 TestCascade cascade(GetDocument());
870 cascade.Add("--a", "var(--b)");
871 cascade.Add("--b", "var(--a)");
872 cascade.Apply();
873
874 EXPECT_FALSE(cascade.ComputedValue("--a"));
875 EXPECT_FALSE(cascade.ComputedValue("--b"));
876 }
877
TEST_F(StyleCascadeTest,FallbackTriggeredByRegisteredCycle)878 TEST_F(StyleCascadeTest, FallbackTriggeredByRegisteredCycle) {
879 RegisterProperty(GetDocument(), "--a", "<length>", "0px", false);
880 RegisterProperty(GetDocument(), "--b", "<length>", "0px", false);
881
882 TestCascade cascade(GetDocument());
883 // Cycle:
884 cascade.Add("--a", "var(--b)");
885 cascade.Add("--b", "var(--a)");
886 // References to cycle:
887 cascade.Add("--c", "var(--a,1px)");
888 cascade.Add("--d", "var(--b,2px)");
889 cascade.Apply();
890
891 EXPECT_FALSE(cascade.ComputedValue("--a"));
892 EXPECT_FALSE(cascade.ComputedValue("--b"));
893 EXPECT_EQ("1px", cascade.ComputedValue("--c"));
894 EXPECT_EQ("2px", cascade.ComputedValue("--d"));
895 }
896
TEST_F(StyleCascadeTest,CycleStillInvalidWithFallback)897 TEST_F(StyleCascadeTest, CycleStillInvalidWithFallback) {
898 TestCascade cascade(GetDocument());
899 // Cycle:
900 cascade.Add("--a", "var(--b,red)");
901 cascade.Add("--b", "var(--a,red)");
902 // References to cycle:
903 cascade.Add("--c", "var(--a,green)");
904 cascade.Add("--d", "var(--b,green)");
905 cascade.Apply();
906
907 EXPECT_FALSE(cascade.ComputedValue("--a"));
908 EXPECT_FALSE(cascade.ComputedValue("--b"));
909 EXPECT_EQ("green", cascade.ComputedValue("--c"));
910 EXPECT_EQ("green", cascade.ComputedValue("--d"));
911 }
912
TEST_F(StyleCascadeTest,CycleInFallbackStillInvalid)913 TEST_F(StyleCascadeTest, CycleInFallbackStillInvalid) {
914 TestCascade cascade(GetDocument());
915 // Cycle:
916 cascade.Add("--a", "var(--b,red)");
917 cascade.Add("--b", "var(--x,var(--a))");
918 // References to cycle:
919 cascade.Add("--c", "var(--a,green)");
920 cascade.Add("--d", "var(--b,green)");
921 cascade.Apply();
922
923 EXPECT_FALSE(cascade.ComputedValue("--a"));
924 EXPECT_FALSE(cascade.ComputedValue("--b"));
925 EXPECT_EQ("green", cascade.ComputedValue("--c"));
926 EXPECT_EQ("green", cascade.ComputedValue("--d"));
927 }
928
TEST_F(StyleCascadeTest,CycleMultiple)929 TEST_F(StyleCascadeTest, CycleMultiple) {
930 TestCascade cascade(GetDocument());
931 // Cycle:
932 cascade.Add("--a", "var(--c, red)");
933 cascade.Add("--b", "var(--c, red)");
934 cascade.Add("--c", "var(--a, blue) var(--b, blue)");
935 // References to cycle:
936 cascade.Add("--d", "var(--a,green)");
937 cascade.Add("--e", "var(--b,green)");
938 cascade.Add("--f", "var(--c,green)");
939 cascade.Apply();
940
941 EXPECT_FALSE(cascade.ComputedValue("--a"));
942 EXPECT_FALSE(cascade.ComputedValue("--b"));
943 EXPECT_FALSE(cascade.ComputedValue("--c"));
944 EXPECT_EQ("green", cascade.ComputedValue("--d"));
945 EXPECT_EQ("green", cascade.ComputedValue("--e"));
946 EXPECT_EQ("green", cascade.ComputedValue("--f"));
947 }
948
TEST_F(StyleCascadeTest,CycleMultipleFallback)949 TEST_F(StyleCascadeTest, CycleMultipleFallback) {
950 TestCascade cascade(GetDocument());
951 // Cycle:
952 cascade.Add("--a", "var(--b, red)");
953 cascade.Add("--b", "var(--a, var(--c, red))");
954 cascade.Add("--c", "var(--b, red)");
955 // References to cycle:
956 cascade.Add("--d", "var(--a,green)");
957 cascade.Add("--e", "var(--b,green)");
958 cascade.Add("--f", "var(--c,green)");
959 cascade.Apply();
960
961 EXPECT_FALSE(cascade.ComputedValue("--a"));
962 EXPECT_FALSE(cascade.ComputedValue("--b"));
963 EXPECT_FALSE(cascade.ComputedValue("--c"));
964 EXPECT_EQ("green", cascade.ComputedValue("--d"));
965 EXPECT_EQ("green", cascade.ComputedValue("--e"));
966 EXPECT_EQ("green", cascade.ComputedValue("--f"));
967 }
968
TEST_F(StyleCascadeTest,CycleMultipleUnusedFallback)969 TEST_F(StyleCascadeTest, CycleMultipleUnusedFallback) {
970 TestCascade cascade(GetDocument());
971 cascade.Add("--a", "red");
972 // Cycle:
973 cascade.Add("--b", "var(--c, red)");
974 cascade.Add("--c", "var(--a, var(--b, red) var(--d, red))");
975 cascade.Add("--d", "var(--c, red)");
976 // References to cycle:
977 cascade.Add("--e", "var(--b,green)");
978 cascade.Add("--f", "var(--c,green)");
979 cascade.Add("--g", "var(--d,green)");
980 cascade.Apply();
981
982 EXPECT_FALSE(cascade.ComputedValue("--b"));
983 EXPECT_FALSE(cascade.ComputedValue("--c"));
984 EXPECT_FALSE(cascade.ComputedValue("--d"));
985 EXPECT_EQ("green", cascade.ComputedValue("--e"));
986 EXPECT_EQ("green", cascade.ComputedValue("--f"));
987 EXPECT_EQ("green", cascade.ComputedValue("--g"));
988 }
989
TEST_F(StyleCascadeTest,CycleReferencedFromStandardProperty)990 TEST_F(StyleCascadeTest, CycleReferencedFromStandardProperty) {
991 TestCascade cascade(GetDocument());
992 cascade.Add("--a", "var(--b)");
993 cascade.Add("--b", "var(--a)");
994 cascade.Add("color:var(--a,green)");
995 cascade.Apply();
996
997 EXPECT_FALSE(cascade.ComputedValue("--a"));
998 EXPECT_FALSE(cascade.ComputedValue("--b"));
999 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
1000 }
1001
TEST_F(StyleCascadeTest,CycleReferencedFromShorthand)1002 TEST_F(StyleCascadeTest, CycleReferencedFromShorthand) {
1003 TestCascade cascade(GetDocument());
1004 cascade.Add("--a", "var(--b)");
1005 cascade.Add("--b", "var(--a)");
1006 cascade.Add("background", "var(--a,green)");
1007 cascade.Apply();
1008
1009 EXPECT_FALSE(cascade.ComputedValue("--a"));
1010 EXPECT_FALSE(cascade.ComputedValue("--b"));
1011 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("background-color"));
1012 }
1013
TEST_F(StyleCascadeTest,EmUnit)1014 TEST_F(StyleCascadeTest, EmUnit) {
1015 TestCascade cascade(GetDocument());
1016 cascade.Add("font-size", "10px");
1017 cascade.Add("width", "10em");
1018 cascade.Apply();
1019
1020 EXPECT_EQ("100px", cascade.ComputedValue("width"));
1021 }
1022
TEST_F(StyleCascadeTest,EmUnitCustomProperty)1023 TEST_F(StyleCascadeTest, EmUnitCustomProperty) {
1024 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1025
1026 TestCascade cascade(GetDocument());
1027 cascade.Add("font-size", "10px");
1028 cascade.Add("--x", "10em");
1029 cascade.Apply();
1030
1031 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1032 }
1033
TEST_F(StyleCascadeTest,EmUnitNonCycle)1034 TEST_F(StyleCascadeTest, EmUnitNonCycle) {
1035 TestCascade parent(GetDocument());
1036 parent.Add("font-size", "10px");
1037 parent.Apply();
1038
1039 TestCascade cascade(GetDocument());
1040 cascade.InheritFrom(parent.TakeStyle());
1041 cascade.Add("font-size", "var(--x)");
1042 cascade.Add("--x", "10em");
1043 cascade.Apply();
1044
1045 // Note: Only registered properties can have cycles with font-size.
1046 EXPECT_EQ("100px", cascade.ComputedValue("font-size"));
1047 }
1048
TEST_F(StyleCascadeTest,EmUnitCycle)1049 TEST_F(StyleCascadeTest, EmUnitCycle) {
1050 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1051
1052 TestCascade cascade(GetDocument());
1053 cascade.Add("font-size", "var(--x)");
1054 cascade.Add("--x", "10em");
1055 cascade.Apply();
1056
1057 EXPECT_FALSE(cascade.ComputedValue("--x"));
1058 }
1059
TEST_F(StyleCascadeTest,SubstitutingEmCycles)1060 TEST_F(StyleCascadeTest, SubstitutingEmCycles) {
1061 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1062
1063 TestCascade cascade(GetDocument());
1064 cascade.Add("font-size", "var(--x)");
1065 cascade.Add("--x", "10em");
1066 cascade.Add("--y", "var(--x)");
1067 cascade.Add("--z", "var(--x,1px)");
1068 cascade.Apply();
1069
1070 EXPECT_FALSE(cascade.ComputedValue("--y"));
1071 EXPECT_EQ("1px", cascade.ComputedValue("--z"));
1072 }
1073
TEST_F(StyleCascadeTest,RemUnit)1074 TEST_F(StyleCascadeTest, RemUnit) {
1075 SetRootFont("10px");
1076 UpdateAllLifecyclePhasesForTest();
1077
1078 TestCascade cascade(GetDocument());
1079 cascade.Add("width", "10rem");
1080 cascade.Apply();
1081
1082 EXPECT_EQ("100px", cascade.ComputedValue("width"));
1083 }
1084
TEST_F(StyleCascadeTest,RemUnitCustomProperty)1085 TEST_F(StyleCascadeTest, RemUnitCustomProperty) {
1086 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1087
1088 SetRootFont("10px");
1089 UpdateAllLifecyclePhasesForTest();
1090
1091 TestCascade cascade(GetDocument());
1092 cascade.Add("--x", "10rem");
1093 cascade.Apply();
1094
1095 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1096 }
1097
TEST_F(StyleCascadeTest,RemUnitInFontSize)1098 TEST_F(StyleCascadeTest, RemUnitInFontSize) {
1099 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1100
1101 SetRootFont("10px");
1102 UpdateAllLifecyclePhasesForTest();
1103
1104 TestCascade cascade(GetDocument());
1105 cascade.Add("font-size", "1rem");
1106 cascade.Add("--x", "10rem");
1107 cascade.Apply();
1108
1109 EXPECT_EQ("100px", cascade.ComputedValue("--x"));
1110 }
1111
TEST_F(StyleCascadeTest,RemUnitInRootFontSizeCycle)1112 TEST_F(StyleCascadeTest, RemUnitInRootFontSizeCycle) {
1113 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1114
1115 TestCascade cascade(GetDocument(), DocumentElement());
1116 cascade.Add("font-size", "var(--x)");
1117 cascade.Add("--x", "1rem");
1118 cascade.Apply();
1119
1120 EXPECT_FALSE(cascade.ComputedValue("--x"));
1121 }
1122
TEST_F(StyleCascadeTest,RemUnitInRootFontSizeNonCycle)1123 TEST_F(StyleCascadeTest, RemUnitInRootFontSizeNonCycle) {
1124 TestCascade cascade(GetDocument(), DocumentElement());
1125 cascade.Add("font-size", "initial");
1126 cascade.Apply();
1127
1128 String expected = cascade.ComputedValue("font-size");
1129
1130 cascade.Add("font-size", "var(--x)");
1131 cascade.Add("--x", "1rem");
1132 cascade.Apply();
1133
1134 // Note: Only registered properties can have cycles with font-size.
1135 EXPECT_EQ("1rem", cascade.ComputedValue("--x"));
1136 EXPECT_EQ(expected, cascade.ComputedValue("font-size"));
1137 }
1138
TEST_F(StyleCascadeTest,Initial)1139 TEST_F(StyleCascadeTest, Initial) {
1140 TestCascade parent(GetDocument());
1141 parent.Add("--x", "foo");
1142 parent.Apply();
1143
1144 TestCascade cascade(GetDocument());
1145 cascade.InheritFrom(parent.TakeStyle());
1146 cascade.Add("--y", "foo");
1147 cascade.Apply();
1148
1149 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1150 EXPECT_EQ("foo", cascade.ComputedValue("--y"));
1151
1152 cascade.Add("--x", "initial");
1153 cascade.Add("--y", "initial");
1154 cascade.Apply();
1155
1156 EXPECT_FALSE(cascade.ComputedValue("--x"));
1157 EXPECT_FALSE(cascade.ComputedValue("--y"));
1158 }
1159
TEST_F(StyleCascadeTest,Inherit)1160 TEST_F(StyleCascadeTest, Inherit) {
1161 TestCascade parent(GetDocument());
1162 parent.Add("--x", "foo");
1163 parent.Apply();
1164
1165 TestCascade cascade(GetDocument());
1166 cascade.InheritFrom(parent.TakeStyle());
1167
1168 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1169
1170 cascade.Add("--x", "bar");
1171 cascade.Apply();
1172 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1173
1174 cascade.Add("--x", "inherit");
1175 cascade.Apply();
1176 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1177 }
1178
TEST_F(StyleCascadeTest,Unset)1179 TEST_F(StyleCascadeTest, Unset) {
1180 TestCascade parent(GetDocument());
1181 parent.Add("--x", "foo");
1182 parent.Apply();
1183
1184 TestCascade cascade(GetDocument());
1185 cascade.InheritFrom(parent.TakeStyle());
1186 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1187
1188 cascade.Add("--x", "bar");
1189 cascade.Apply();
1190 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1191
1192 cascade.Add("--x", "unset");
1193 cascade.Apply();
1194 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1195 }
1196
TEST_F(StyleCascadeTest,RegisteredInitial)1197 TEST_F(StyleCascadeTest, RegisteredInitial) {
1198 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1199
1200 TestCascade cascade(GetDocument());
1201 cascade.Apply();
1202 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1203 }
1204
TEST_F(StyleCascadeTest,SubstituteRegisteredImplicitInitialValue)1205 TEST_F(StyleCascadeTest, SubstituteRegisteredImplicitInitialValue) {
1206 RegisterProperty(GetDocument(), "--x", "<length>", "13px", false);
1207
1208 TestCascade cascade(GetDocument());
1209 cascade.Add("--y", " var(--x) ");
1210 cascade.Apply();
1211 EXPECT_EQ("13px", cascade.ComputedValue("--x"));
1212 EXPECT_EQ(" 13px ", cascade.ComputedValue("--y"));
1213 }
1214
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversal)1215 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversal) {
1216 RegisterProperty(GetDocument(), "--x", "*", "foo", false);
1217
1218 TestCascade cascade(GetDocument());
1219 cascade.Add("--x", "bar");
1220 cascade.Add("--y", "var(--x)");
1221 cascade.Apply();
1222 EXPECT_EQ("bar", cascade.ComputedValue("--x"));
1223 EXPECT_EQ("bar", cascade.ComputedValue("--y"));
1224 }
1225
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversalInvalid)1226 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversalInvalid) {
1227 RegisterProperty(GetDocument(), "--x", "*", g_null_atom, false);
1228
1229 TestCascade cascade(GetDocument());
1230 cascade.Add("--y", " var(--x) ");
1231 cascade.Apply();
1232 EXPECT_FALSE(cascade.ComputedValue("--x"));
1233 EXPECT_FALSE(cascade.ComputedValue("--y"));
1234 }
1235
TEST_F(StyleCascadeTest,SubstituteRegisteredUniversalInitial)1236 TEST_F(StyleCascadeTest, SubstituteRegisteredUniversalInitial) {
1237 RegisterProperty(GetDocument(), "--x", "*", "foo", false);
1238
1239 TestCascade cascade(GetDocument());
1240 cascade.Add("--y", " var(--x) ");
1241 cascade.Apply();
1242 EXPECT_EQ("foo", cascade.ComputedValue("--x"));
1243 EXPECT_EQ(" foo ", cascade.ComputedValue("--y"));
1244 }
1245
TEST_F(StyleCascadeTest,RegisteredExplicitInitial)1246 TEST_F(StyleCascadeTest, RegisteredExplicitInitial) {
1247 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1248
1249 TestCascade cascade(GetDocument());
1250 cascade.Add("--x", "10px");
1251 cascade.Apply();
1252 EXPECT_EQ("10px", cascade.ComputedValue("--x"));
1253
1254 cascade.Add("--x", "initial");
1255 cascade.Add("--y", "var(--x)");
1256 cascade.Apply();
1257 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1258 EXPECT_EQ("0px", cascade.ComputedValue("--y"));
1259 }
1260
TEST_F(StyleCascadeTest,RegisteredExplicitInherit)1261 TEST_F(StyleCascadeTest, RegisteredExplicitInherit) {
1262 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1263
1264 TestCascade parent(GetDocument());
1265 parent.Add("--x", "15px");
1266 parent.Apply();
1267 EXPECT_EQ("15px", parent.ComputedValue("--x"));
1268
1269 TestCascade cascade(GetDocument());
1270 cascade.InheritFrom(parent.TakeStyle());
1271 cascade.Apply();
1272 EXPECT_EQ("0px", cascade.ComputedValue("--x")); // Note: inherit==false
1273
1274 cascade.Add("--x", "inherit");
1275 cascade.Add("--y", "var(--x)");
1276 cascade.Apply();
1277 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1278 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1279 }
1280
TEST_F(StyleCascadeTest,RegisteredExplicitUnset)1281 TEST_F(StyleCascadeTest, RegisteredExplicitUnset) {
1282 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1283 RegisterProperty(GetDocument(), "--y", "<length>", "0px", true);
1284
1285 TestCascade parent(GetDocument());
1286 parent.Add("--x", "15px");
1287 parent.Add("--y", "15px");
1288 parent.Apply();
1289 EXPECT_EQ("15px", parent.ComputedValue("--x"));
1290 EXPECT_EQ("15px", parent.ComputedValue("--y"));
1291
1292 TestCascade cascade(GetDocument());
1293 cascade.InheritFrom(parent.TakeStyle());
1294 cascade.Add("--x", "2px");
1295 cascade.Add("--y", "2px");
1296 cascade.Apply();
1297 EXPECT_EQ("2px", cascade.ComputedValue("--x"));
1298 EXPECT_EQ("2px", cascade.ComputedValue("--y"));
1299
1300 cascade.Add("--x", "unset");
1301 cascade.Add("--y", "unset");
1302 cascade.Add("--z", "var(--x) var(--y)");
1303 cascade.Apply();
1304 EXPECT_EQ("0px", cascade.ComputedValue("--x"));
1305 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1306 EXPECT_EQ("0px 15px", cascade.ComputedValue("--z"));
1307 }
1308
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInCustomProperty)1309 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInCustomProperty) {
1310 TestCascade cascade(GetDocument());
1311 cascade.Add(AnimationTaintedSet("--x", "15px"));
1312 cascade.Add("--y", "var(--x)");
1313 cascade.Apply();
1314 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1315 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1316 }
1317
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInStandardProperty)1318 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInStandardProperty) {
1319 TestCascade cascade(GetDocument());
1320 cascade.Add(AnimationTaintedSet("--x", "15px"));
1321 cascade.Add("width", "var(--x)");
1322 cascade.Apply();
1323 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1324 EXPECT_EQ("15px", cascade.ComputedValue("width"));
1325 }
1326
TEST_F(StyleCascadeTest,SubstituteAnimationTaintedInAnimationProperty)1327 TEST_F(StyleCascadeTest, SubstituteAnimationTaintedInAnimationProperty) {
1328 TestCascade cascade(GetDocument());
1329 cascade.Add("--x", "20s");
1330 cascade.Add("animation-duration", "var(--x)");
1331 cascade.Apply();
1332
1333 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
1334 EXPECT_EQ("20s", cascade.ComputedValue("animation-duration"));
1335
1336 cascade.Add(AnimationTaintedSet("--y", "20s"));
1337 cascade.Add("animation-duration", "var(--y)");
1338 cascade.Apply();
1339
1340 EXPECT_EQ("20s", cascade.ComputedValue("--y"));
1341 EXPECT_EQ("0s", cascade.ComputedValue("animation-duration"));
1342 }
1343
TEST_F(StyleCascadeTest,IndirectlyAnimationTainted)1344 TEST_F(StyleCascadeTest, IndirectlyAnimationTainted) {
1345 TestCascade cascade(GetDocument());
1346 cascade.Add(AnimationTaintedSet("--x", "20s"));
1347 cascade.Add("--y", "var(--x)");
1348 cascade.Add("animation-duration", "var(--y)");
1349 cascade.Apply();
1350
1351 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
1352 EXPECT_EQ("20s", cascade.ComputedValue("--y"));
1353 EXPECT_EQ("0s", cascade.ComputedValue("animation-duration"));
1354 }
1355
TEST_F(StyleCascadeTest,AnimationTaintedFallback)1356 TEST_F(StyleCascadeTest, AnimationTaintedFallback) {
1357 TestCascade cascade(GetDocument());
1358 cascade.Add(AnimationTaintedSet("--x", "20s"));
1359 cascade.Add("animation-duration", "var(--x,1s)");
1360 cascade.Apply();
1361
1362 EXPECT_EQ("20s", cascade.ComputedValue("--x"));
1363 EXPECT_EQ("1s", cascade.ComputedValue("animation-duration"));
1364 }
1365
TEST_F(StyleCascadeTest,EnvMissingNestedVar)1366 TEST_F(StyleCascadeTest, EnvMissingNestedVar) {
1367 TestCascade cascade(GetDocument());
1368 cascade.Add("--x", "rgb(0, 0, 0)");
1369 cascade.Add("background-color", "env(missing, var(--x))");
1370 cascade.Apply();
1371
1372 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("--x"));
1373 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("background-color"));
1374 }
1375
TEST_F(StyleCascadeTest,EnvMissingNestedVarFallback)1376 TEST_F(StyleCascadeTest, EnvMissingNestedVarFallback) {
1377 TestCascade cascade(GetDocument());
1378 cascade.Add("background-color", "env(missing, var(--missing, blue))");
1379 cascade.Apply();
1380
1381 EXPECT_EQ("rgb(0, 0, 255)", cascade.ComputedValue("background-color"));
1382 }
1383
TEST_F(StyleCascadeTest,EnvMissingFallback)1384 TEST_F(StyleCascadeTest, EnvMissingFallback) {
1385 TestCascade cascade(GetDocument());
1386 cascade.Add("background-color", "env(missing, blue)");
1387 cascade.Apply();
1388
1389 EXPECT_EQ("rgb(0, 0, 255)", cascade.ComputedValue("background-color"));
1390 }
1391
TEST_F(StyleCascadeTest,ValidEnv)1392 TEST_F(StyleCascadeTest, ValidEnv) {
1393 AutoEnv env(*this, "test", "red");
1394
1395 TestCascade cascade(GetDocument());
1396 cascade.Add("background-color", "env(test, blue)");
1397 cascade.Apply();
1398
1399 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
1400 }
1401
TEST_F(StyleCascadeTest,ValidEnvFallback)1402 TEST_F(StyleCascadeTest, ValidEnvFallback) {
1403 AutoEnv env(*this, "test", "red");
1404
1405 TestCascade cascade(GetDocument());
1406 cascade.Add("background-color", "env(test, blue)");
1407 cascade.Apply();
1408
1409 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
1410 }
1411
TEST_F(StyleCascadeTest,ValidEnvInUnusedFallback)1412 TEST_F(StyleCascadeTest, ValidEnvInUnusedFallback) {
1413 AutoEnv env(*this, "test", "red");
1414
1415 TestCascade cascade(GetDocument());
1416 cascade.Add("--x", "rgb(0, 0, 0)");
1417 cascade.Add("background-color", "var(--x, env(test))");
1418 cascade.Apply();
1419
1420 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("--x"));
1421 EXPECT_EQ("rgb(0, 0, 0)", cascade.ComputedValue("background-color"));
1422 }
1423
TEST_F(StyleCascadeTest,ValidEnvInUsedFallback)1424 TEST_F(StyleCascadeTest, ValidEnvInUsedFallback) {
1425 AutoEnv env(*this, "test", "red");
1426
1427 TestCascade cascade(GetDocument());
1428 cascade.Add("background-color", "var(--missing, env(test))");
1429 cascade.Apply();
1430
1431 EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color"));
1432 }
1433
TEST_F(StyleCascadeTest,AnimationApplyFilter)1434 TEST_F(StyleCascadeTest, AnimationApplyFilter) {
1435 AppendSheet(R"HTML(
1436 @keyframes test {
1437 from { color: white; background-color: white; }
1438 to { color: gray; background-color: gray; }
1439 }
1440 )HTML");
1441
1442 TestCascade cascade(GetDocument());
1443
1444 cascade.Add("animation: test linear 10s -5s");
1445 cascade.Add("color:green");
1446 cascade.Apply();
1447
1448 cascade.CalculateAnimationUpdate();
1449 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
1450
1451 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
1452 EXPECT_EQ("rgb(192, 192, 192)", cascade.ComputedValue("background-color"));
1453 }
1454
TEST_F(StyleCascadeTest,TransitionApplyFilter)1455 TEST_F(StyleCascadeTest, TransitionApplyFilter) {
1456 TestCascade cascade1(GetDocument());
1457 cascade1.Add("background-color: white");
1458 cascade1.Add("color: white");
1459 cascade1.Add("transition: all steps(2, start) 100s");
1460 cascade1.Apply();
1461
1462 // Set the old style on the element, so that the transition
1463 // update detects it.
1464 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
1465
1466 // Now simulate a new style, with new color values.
1467 TestCascade cascade2(GetDocument());
1468 cascade2.Add("background-color: gray");
1469 cascade2.Add("color: gray");
1470 cascade2.Add("transition: all steps(2, start) 100s");
1471 cascade2.Apply();
1472
1473 cascade2.CalculateTransitionUpdate();
1474 cascade2.Apply(CascadeFilter(CSSProperty::kInherited, true));
1475
1476 EXPECT_EQ("rgb(128, 128, 128)", cascade2.ComputedValue("color"));
1477 EXPECT_EQ("rgb(192, 192, 192)", cascade2.ComputedValue("background-color"));
1478 }
1479
TEST_F(StyleCascadeTest,PendingKeyframeAnimation)1480 TEST_F(StyleCascadeTest, PendingKeyframeAnimation) {
1481 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1482
1483 AppendSheet(R"HTML(
1484 @keyframes test {
1485 from { --x: 10px; }
1486 to { --x: 20px; }
1487 }
1488 )HTML");
1489
1490 TestCascade cascade(GetDocument());
1491
1492 cascade.Add("animation-name", "test");
1493 cascade.Add("animation-duration", "1s");
1494 cascade.Apply();
1495
1496 cascade.CalculateAnimationUpdate();
1497 cascade.Apply();
1498
1499 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
1500 }
1501
TEST_F(StyleCascadeTest,PendingKeyframeAnimationApply)1502 TEST_F(StyleCascadeTest, PendingKeyframeAnimationApply) {
1503 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1504
1505 AppendSheet(R"HTML(
1506 @keyframes test {
1507 from { --x: 10px; }
1508 to { --x: 20px; }
1509 }
1510 )HTML");
1511
1512 TestCascade cascade(GetDocument());
1513
1514 cascade.Add("animation-name", "test");
1515 cascade.Add("animation-duration", "10s");
1516 cascade.Add("animation-timing-function", "linear");
1517 cascade.Add("animation-delay", "-5s");
1518 cascade.Apply();
1519
1520 cascade.CalculateAnimationUpdate();
1521 cascade.Apply();
1522
1523 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin());
1524 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1525 }
1526
TEST_F(StyleCascadeTest,TransitionCausesInterpolationValue)1527 TEST_F(StyleCascadeTest, TransitionCausesInterpolationValue) {
1528 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1529
1530 // First, simulate an "old style".
1531 TestCascade cascade1(GetDocument());
1532 cascade1.Add("--x", "10px");
1533 cascade1.Add("transition", "--x 1s");
1534 cascade1.Apply();
1535
1536 // Set the old style on the element, so that the animation
1537 // update detects it.
1538 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
1539
1540 // Now simulate a new style, with a new value for --x.
1541 TestCascade cascade2(GetDocument());
1542 cascade2.Add("--x", "20px");
1543 cascade2.Add("transition", "--x 1s");
1544 cascade2.Apply();
1545
1546 cascade2.CalculateTransitionUpdate();
1547 cascade2.Apply();
1548
1549 EXPECT_EQ(CascadeOrigin::kTransition,
1550 cascade2.GetPriority("--x").GetOrigin());
1551 }
1552
TEST_F(StyleCascadeTest,TransitionDetectedForChangedFontSize)1553 TEST_F(StyleCascadeTest, TransitionDetectedForChangedFontSize) {
1554 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1555
1556 TestCascade cascade1(GetDocument());
1557 cascade1.Add("font-size", "10px");
1558 cascade1.Add("--x", "10em");
1559 cascade1.Add("width", "10em");
1560 cascade1.Add("height", "10px");
1561 cascade1.Add("transition", "--x 1s, width 1s");
1562 cascade1.Apply();
1563
1564 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
1565
1566 TestCascade cascade2(GetDocument());
1567 cascade2.Add("font-size", "20px");
1568 cascade2.Add("--x", "10em");
1569 cascade2.Add("width", "10em");
1570 cascade2.Add("height", "10px");
1571 cascade2.Add("transition", "--x 1s, width 1s");
1572 cascade2.Apply();
1573
1574 cascade2.CalculateTransitionUpdate();
1575 cascade2.Apply();
1576
1577 EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("--x"));
1578 EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("width"));
1579 EXPECT_EQ("10px", cascade2.ComputedValue("height"));
1580 }
1581
TEST_F(StyleCascadeTest,AnimatingVarReferences)1582 TEST_F(StyleCascadeTest, AnimatingVarReferences) {
1583 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1584
1585 AppendSheet(R"HTML(
1586 @keyframes test {
1587 from { --x: var(--from); }
1588 to { --x: var(--to); }
1589 }
1590 )HTML");
1591
1592 TestCascade cascade(GetDocument());
1593
1594 cascade.Add("animation-name", "test");
1595 cascade.Add("animation-duration", "10s");
1596 cascade.Add("animation-timing-function", "linear");
1597 cascade.Add("animation-delay", "-5s");
1598 cascade.Apply();
1599
1600 cascade.CalculateAnimationUpdate();
1601 cascade.Add("--from", "10px");
1602 cascade.Add("--to", "20px");
1603 cascade.Add("--y", "var(--x)");
1604 cascade.Apply();
1605
1606 EXPECT_EQ("15px", cascade.ComputedValue("--x"));
1607 EXPECT_EQ("15px", cascade.ComputedValue("--y"));
1608 }
1609
TEST_F(StyleCascadeTest,AnimateStandardProperty)1610 TEST_F(StyleCascadeTest, AnimateStandardProperty) {
1611 AppendSheet(R"HTML(
1612 @keyframes test {
1613 from { width: 10px; }
1614 to { width: 20px; }
1615 }
1616 )HTML");
1617
1618 TestCascade cascade(GetDocument());
1619
1620 cascade.Add("animation-name", "test");
1621 cascade.Add("animation-duration", "10s");
1622 cascade.Add("animation-timing-function", "linear");
1623 cascade.Add("animation-delay", "-5s");
1624 cascade.Apply();
1625
1626 cascade.CalculateAnimationUpdate();
1627 cascade.Apply();
1628
1629 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
1630 EXPECT_EQ("15px", cascade.ComputedValue("width"));
1631 }
1632
TEST_F(StyleCascadeTest,AuthorImportantWinOverAnimations)1633 TEST_F(StyleCascadeTest, AuthorImportantWinOverAnimations) {
1634 AppendSheet(R"HTML(
1635 @keyframes test {
1636 from { width: 10px; height: 10px; }
1637 to { width: 20px; height: 20px; }
1638 }
1639 )HTML");
1640
1641 TestCascade cascade(GetDocument());
1642
1643 cascade.Add("animation-name", "test");
1644 cascade.Add("animation-duration", "10s");
1645 cascade.Add("animation-timing-function", "linear");
1646 cascade.Add("animation-delay", "-5s");
1647 cascade.Add("width:40px");
1648 cascade.Add("height:40px !important");
1649 cascade.Apply();
1650
1651 cascade.CalculateAnimationUpdate();
1652 cascade.Apply();
1653
1654 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width"));
1655 EXPECT_EQ(CascadeOrigin::kAuthor, cascade.GetOrigin("height"));
1656
1657 EXPECT_EQ("15px", cascade.ComputedValue("width"));
1658 EXPECT_EQ("40px", cascade.ComputedValue("height"));
1659 }
1660
TEST_F(StyleCascadeTest,TransitionsWinOverAuthorImportant)1661 TEST_F(StyleCascadeTest, TransitionsWinOverAuthorImportant) {
1662 // First, simulate an "old style".
1663 TestCascade cascade1(GetDocument());
1664 cascade1.Add("width:10px !important");
1665 cascade1.Add("height:10px !important");
1666 cascade1.Add("transition:all 1s");
1667 cascade1.Apply();
1668
1669 // Set the old style on the element, so that the animation
1670 // update detects it.
1671 GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
1672
1673 // Now simulate a new style, with a new value for width/height.
1674 TestCascade cascade2(GetDocument());
1675 cascade2.Add("width:20px !important");
1676 cascade2.Add("height:20px !important");
1677 cascade2.Add("transition:all 1s");
1678 cascade2.Apply();
1679
1680 cascade2.CalculateTransitionUpdate();
1681 cascade2.Apply();
1682
1683 EXPECT_EQ(CascadeOrigin::kTransition,
1684 cascade2.GetPriority("width").GetOrigin());
1685 EXPECT_EQ(CascadeOrigin::kTransition,
1686 cascade2.GetPriority("height").GetOrigin());
1687 }
1688
TEST_F(StyleCascadeTest,EmRespondsToAnimatedFontSize)1689 TEST_F(StyleCascadeTest, EmRespondsToAnimatedFontSize) {
1690 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1691
1692 AppendSheet(R"HTML(
1693 @keyframes test {
1694 from { font-size: 10px; }
1695 to { font-size: 20px; }
1696 }
1697 )HTML");
1698
1699 TestCascade cascade(GetDocument());
1700
1701 cascade.Add("animation-name", "test");
1702 cascade.Add("animation-duration", "10s");
1703 cascade.Add("animation-timing-function", "linear");
1704 cascade.Add("animation-delay", "-5s");
1705 cascade.Apply();
1706
1707 cascade.CalculateAnimationUpdate();
1708 cascade.Add("--x", "2em");
1709 cascade.Add("width", "10em");
1710
1711 cascade.Apply();
1712 EXPECT_EQ("30px", cascade.ComputedValue("--x"));
1713 EXPECT_EQ("150px", cascade.ComputedValue("width"));
1714 }
1715
TEST_F(StyleCascadeTest,AnimateStandardPropertyWithVar)1716 TEST_F(StyleCascadeTest, AnimateStandardPropertyWithVar) {
1717 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1718
1719 AppendSheet(R"HTML(
1720 @keyframes test {
1721 from { width: var(--from); }
1722 to { width: var(--to); }
1723 }
1724 )HTML");
1725
1726 TestCascade cascade(GetDocument());
1727
1728 cascade.Add("animation-name", "test");
1729 cascade.Add("animation-duration", "10s");
1730 cascade.Add("animation-timing-function", "linear");
1731 cascade.Add("animation-delay", "-5s");
1732 cascade.Apply();
1733
1734 cascade.CalculateAnimationUpdate();
1735 cascade.Add("--from", "10px");
1736 cascade.Add("--to", "20px");
1737
1738 cascade.Apply();
1739 EXPECT_EQ("15px", cascade.ComputedValue("width"));
1740 }
1741
TEST_F(StyleCascadeTest,AnimateStandardShorthand)1742 TEST_F(StyleCascadeTest, AnimateStandardShorthand) {
1743 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1744
1745 AppendSheet(R"HTML(
1746 @keyframes test {
1747 from { margin: 10px; }
1748 to { margin: 20px; }
1749 }
1750 )HTML");
1751
1752 TestCascade cascade(GetDocument());
1753
1754 cascade.Add("animation-name", "test");
1755 cascade.Add("animation-duration", "10s");
1756 cascade.Add("animation-timing-function", "linear");
1757 cascade.Add("animation-delay", "-5s");
1758 cascade.Apply();
1759
1760 cascade.CalculateAnimationUpdate();
1761 cascade.Apply();
1762
1763 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
1764 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right"));
1765 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom"));
1766 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
1767
1768 EXPECT_EQ("15px", cascade.ComputedValue("margin-top"));
1769 EXPECT_EQ("15px", cascade.ComputedValue("margin-right"));
1770 EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom"));
1771 EXPECT_EQ("15px", cascade.ComputedValue("margin-left"));
1772 }
1773
TEST_F(StyleCascadeTest,AnimatedVisitedImportantOverride)1774 TEST_F(StyleCascadeTest, AnimatedVisitedImportantOverride) {
1775 AppendSheet(R"HTML(
1776 @keyframes test {
1777 from { background-color: rgb(100, 100, 100); }
1778 to { background-color: rgb(200, 200, 200); }
1779 }
1780 )HTML");
1781
1782 TestCascade cascade(GetDocument());
1783 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
1784
1785 cascade.Add(ParseDeclarationBlock("background-color:red !important"),
1786 CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
1787 cascade.Add("animation-name:test");
1788 cascade.Add("animation-duration:10s");
1789 cascade.Add("animation-timing-function:linear");
1790 cascade.Add("animation-delay:-5s");
1791 cascade.Apply();
1792
1793 cascade.CalculateAnimationUpdate();
1794 cascade.Apply();
1795 EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("background-color"));
1796
1797 auto style = cascade.TakeStyle();
1798
1799 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
1800 EXPECT_EQ(Color(255, 0, 0),
1801 style->VisitedDependentColor(GetCSSPropertyBackgroundColor()));
1802
1803 style->SetInsideLink(EInsideLink::kNotInsideLink);
1804 EXPECT_EQ(Color(150, 150, 150),
1805 style->VisitedDependentColor(GetCSSPropertyBackgroundColor()));
1806 }
1807
TEST_F(StyleCascadeTest,AnimatedVisitedHighPrio)1808 TEST_F(StyleCascadeTest, AnimatedVisitedHighPrio) {
1809 AppendSheet(R"HTML(
1810 @keyframes test {
1811 from { color: rgb(100, 100, 100); }
1812 to { color: rgb(200, 200, 200); }
1813 }
1814 )HTML");
1815
1816 TestCascade cascade(GetDocument());
1817 cascade.Add("color:red");
1818 cascade.Add("animation:test 10s -5s linear");
1819 cascade.Apply();
1820
1821 cascade.CalculateAnimationUpdate();
1822 cascade.Apply();
1823 EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("color"));
1824
1825 auto style = cascade.TakeStyle();
1826
1827 style->SetInsideLink(EInsideLink::kInsideVisitedLink);
1828 EXPECT_EQ(Color(150, 150, 150),
1829 style->VisitedDependentColor(GetCSSPropertyColor()));
1830
1831 style->SetInsideLink(EInsideLink::kNotInsideLink);
1832 EXPECT_EQ(Color(150, 150, 150),
1833 style->VisitedDependentColor(GetCSSPropertyColor()));
1834 }
1835
TEST_F(StyleCascadeTest,AnimatedImportantOverrideFlag)1836 TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlag) {
1837 AppendSheet(R"HTML(
1838 @keyframes test {
1839 from { background-color: white; }
1840 to { background-color: gray; }
1841 }
1842 )HTML");
1843
1844 TestCascade cascade(GetDocument());
1845 cascade.Add("animation:test 10s -5s linear");
1846 cascade.Add("background-color: green !important");
1847 cascade.Apply();
1848 EXPECT_FALSE(cascade.State().HasImportantOverrides());
1849
1850 cascade.CalculateAnimationUpdate();
1851 cascade.Apply();
1852 EXPECT_TRUE(cascade.State().HasImportantOverrides());
1853 }
1854
TEST_F(StyleCascadeTest,AnimatedImportantOverrideNoFlag)1855 TEST_F(StyleCascadeTest, AnimatedImportantOverrideNoFlag) {
1856 AppendSheet(R"HTML(
1857 @keyframes test {
1858 from { background-color: white; }
1859 to { background-color: gray; }
1860 }
1861 )HTML");
1862
1863 TestCascade cascade(GetDocument());
1864 cascade.Add("animation:test 10s -5s linear");
1865 cascade.Add("color:green !important");
1866 cascade.Apply();
1867 EXPECT_FALSE(cascade.State().HasImportantOverrides());
1868
1869 cascade.CalculateAnimationUpdate();
1870 cascade.Apply();
1871 EXPECT_FALSE(cascade.State().HasImportantOverrides());
1872 }
1873
TEST_F(StyleCascadeTest,AnimatedImportantOverrideFlagHighPriority)1874 TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlagHighPriority) {
1875 AppendSheet(R"HTML(
1876 @keyframes test {
1877 from { color: white; }
1878 to { color: gray; }
1879 }
1880 )HTML");
1881
1882 // 'color' is a high priority property, and therefore applied by lookup.
1883 TestCascade cascade(GetDocument());
1884 cascade.Add("animation:test 10s -5s linear");
1885 cascade.Add("color:green !important");
1886 cascade.Apply();
1887 EXPECT_FALSE(cascade.State().HasImportantOverrides());
1888
1889 cascade.CalculateAnimationUpdate();
1890 cascade.Apply();
1891 EXPECT_TRUE(cascade.State().HasImportantOverrides());
1892 }
1893
TEST_F(StyleCascadeTest,AnimatedImportantOverrideFlagVisited)1894 TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlagVisited) {
1895 AppendSheet(R"HTML(
1896 @keyframes test {
1897 from { background-color: white; }
1898 to { background-color: gray; }
1899 }
1900 )HTML");
1901
1902 TestCascade cascade(GetDocument());
1903 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
1904
1905 cascade.Add(ParseDeclarationBlock("background-color:red !important"),
1906 CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
1907 cascade.Add("animation:test 10s -5s linear");
1908 cascade.Apply();
1909 EXPECT_FALSE(cascade.State().HasImportantOverrides());
1910
1911 cascade.CalculateAnimationUpdate();
1912 cascade.Apply();
1913 EXPECT_TRUE(cascade.State().HasImportantOverrides());
1914 }
1915
TEST_F(StyleCascadeTest,AnimatePendingSubstitutionValue)1916 TEST_F(StyleCascadeTest, AnimatePendingSubstitutionValue) {
1917 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
1918
1919 AppendSheet(R"HTML(
1920 @keyframes test {
1921 from { margin: var(--from); }
1922 to { margin: var(--to); }
1923 }
1924 )HTML");
1925
1926 TestCascade cascade(GetDocument());
1927
1928 cascade.Add("animation-name", "test");
1929 cascade.Add("animation-duration", "10s");
1930 cascade.Add("animation-timing-function", "linear");
1931 cascade.Add("animation-delay", "-5s");
1932 cascade.Apply();
1933
1934 cascade.CalculateAnimationUpdate();
1935 cascade.Add("--from", "10px");
1936 cascade.Add("--to", "20px");
1937 cascade.Apply();
1938
1939 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top"));
1940 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right"));
1941 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom"));
1942 EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
1943
1944 EXPECT_EQ("15px", cascade.ComputedValue("margin-top"));
1945 EXPECT_EQ("15px", cascade.ComputedValue("margin-right"));
1946 EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom"));
1947 EXPECT_EQ("15px", cascade.ComputedValue("margin-left"));
1948 }
1949
TEST_F(StyleCascadeTest,ForeignObjectZoomVsEffectiveZoom)1950 TEST_F(StyleCascadeTest, ForeignObjectZoomVsEffectiveZoom) {
1951 GetDocument().body()->setInnerHTML(R"HTML(
1952 <svg>
1953 <foreignObject id='foreign'></foreignObject>
1954 </svg>
1955 )HTML");
1956 UpdateAllLifecyclePhasesForTest();
1957
1958 Element* foreign_object = GetDocument().getElementById("foreign");
1959 ASSERT_TRUE(foreign_object);
1960
1961 TestCascade cascade(GetDocument(), foreign_object);
1962 cascade.Add("-internal-effective-zoom:initial !important",
1963 CascadeOrigin::kUserAgent);
1964 cascade.Add("zoom:200%");
1965 cascade.Apply();
1966
1967 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
1968 }
1969
TEST_F(StyleCascadeTest,ZoomCascadeOrder)1970 TEST_F(StyleCascadeTest, ZoomCascadeOrder) {
1971 TestCascade cascade(GetDocument());
1972 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
1973 cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kUserAgent);
1974 cascade.Apply();
1975
1976 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
1977 }
1978
TEST_F(StyleCascadeTest,ZoomVsAll)1979 TEST_F(StyleCascadeTest, ZoomVsAll) {
1980 TestCascade cascade(GetDocument());
1981 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
1982 cascade.Add("all:initial");
1983 cascade.Apply();
1984
1985 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
1986 }
1987
TEST_F(StyleCascadeTest,InternalEffectiveZoomVsAll)1988 TEST_F(StyleCascadeTest, InternalEffectiveZoomVsAll) {
1989 TestCascade cascade(GetDocument());
1990 cascade.Add("-internal-effective-zoom:200%", CascadeOrigin::kUserAgent);
1991 cascade.Add("all:initial");
1992 cascade.Apply();
1993
1994 EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
1995 }
1996
TEST_F(StyleCascadeTest,ZoomReversedCascadeOrder)1997 TEST_F(StyleCascadeTest, ZoomReversedCascadeOrder) {
1998 TestCascade cascade(GetDocument());
1999 cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kUserAgent);
2000 cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
2001 cascade.Apply();
2002
2003 EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
2004 }
2005
TEST_F(StyleCascadeTest,ZoomImportant)2006 TEST_F(StyleCascadeTest, ZoomImportant) {
2007 TestCascade cascade(GetDocument());
2008 cascade.Add("zoom:200% !important", CascadeOrigin::kUserAgent);
2009 cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kAuthor);
2010 cascade.Apply();
2011
2012 EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
2013 }
2014
TEST_F(StyleCascadeTest,WritingModeCascadeOrder)2015 TEST_F(StyleCascadeTest, WritingModeCascadeOrder) {
2016 TestCascade cascade(GetDocument());
2017 cascade.Add("writing-mode", "vertical-lr");
2018 cascade.Add("-webkit-writing-mode", "vertical-rl");
2019 cascade.Apply();
2020
2021 EXPECT_EQ("vertical-rl", cascade.ComputedValue("writing-mode"));
2022 EXPECT_EQ("vertical-rl", cascade.ComputedValue("-webkit-writing-mode"));
2023 }
2024
TEST_F(StyleCascadeTest,WritingModeReversedCascadeOrder)2025 TEST_F(StyleCascadeTest, WritingModeReversedCascadeOrder) {
2026 TestCascade cascade(GetDocument());
2027 cascade.Add("-webkit-writing-mode", "vertical-rl");
2028 cascade.Add("writing-mode", "vertical-lr");
2029 cascade.Apply();
2030
2031 EXPECT_EQ("vertical-lr", cascade.ComputedValue("writing-mode"));
2032 EXPECT_EQ("vertical-lr", cascade.ComputedValue("-webkit-writing-mode"));
2033 }
2034
TEST_F(StyleCascadeTest,WritingModePriority)2035 TEST_F(StyleCascadeTest, WritingModePriority) {
2036 TestCascade cascade(GetDocument());
2037 cascade.Add("writing-mode:vertical-lr !important", Origin::kAuthor);
2038 cascade.Add("-webkit-writing-mode:vertical-rl", Origin::kAuthor);
2039 cascade.Apply();
2040
2041 EXPECT_EQ("vertical-lr", cascade.ComputedValue("writing-mode"));
2042 EXPECT_EQ("vertical-lr", cascade.ComputedValue("-webkit-writing-mode"));
2043 }
2044
TEST_F(StyleCascadeTest,WebkitBorderImageCascadeOrder)2045 TEST_F(StyleCascadeTest, WebkitBorderImageCascadeOrder) {
2046 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2047 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2048
2049 TestCascade cascade(GetDocument());
2050 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2051 Origin::kAuthor);
2052 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2053 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2054 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2055 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2056 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2057 cascade.Apply();
2058
2059 EXPECT_EQ(gradient2, cascade.ComputedValue("border-image-source"));
2060 EXPECT_EQ("20", cascade.ComputedValue("border-image-slice"));
2061 EXPECT_EQ("6px", cascade.ComputedValue("border-image-width"));
2062 EXPECT_EQ("4px", cascade.ComputedValue("border-image-outset"));
2063 EXPECT_EQ("space", cascade.ComputedValue("border-image-repeat"));
2064 }
2065
TEST_F(StyleCascadeTest,WebkitBorderImageReverseCascadeOrder)2066 TEST_F(StyleCascadeTest, WebkitBorderImageReverseCascadeOrder) {
2067 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2068 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2069
2070 TestCascade cascade(GetDocument());
2071 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2072 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2073 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2074 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2075 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2076 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2077 Origin::kAuthor);
2078 cascade.Apply();
2079
2080 EXPECT_EQ(gradient1, cascade.ComputedValue("border-image-source"));
2081 EXPECT_EQ("40 fill", cascade.ComputedValue("border-image-slice"));
2082 EXPECT_EQ("10px", cascade.ComputedValue("border-image-width"));
2083 EXPECT_EQ("20px", cascade.ComputedValue("border-image-outset"));
2084 EXPECT_EQ("round", cascade.ComputedValue("border-image-repeat"));
2085 }
2086
TEST_F(StyleCascadeTest,WebkitBorderImageMixedOrder)2087 TEST_F(StyleCascadeTest, WebkitBorderImageMixedOrder) {
2088 String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
2089 String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
2090
2091 TestCascade cascade(GetDocument());
2092 cascade.Add("border-image-source", gradient2, Origin::kAuthor);
2093 cascade.Add("border-image-width", "6px", Origin::kAuthor);
2094 cascade.Add("-webkit-border-image", gradient1 + " round 40 / 10px / 20px",
2095 Origin::kAuthor);
2096 cascade.Add("border-image-slice", "20", Origin::kAuthor);
2097 cascade.Add("border-image-outset", "4px", Origin::kAuthor);
2098 cascade.Add("border-image-repeat", "space", Origin::kAuthor);
2099 cascade.Apply();
2100
2101 EXPECT_EQ(gradient1, cascade.ComputedValue("border-image-source"));
2102 EXPECT_EQ("20", cascade.ComputedValue("border-image-slice"));
2103 EXPECT_EQ("10px", cascade.ComputedValue("border-image-width"));
2104 EXPECT_EQ("4px", cascade.ComputedValue("border-image-outset"));
2105 EXPECT_EQ("space", cascade.ComputedValue("border-image-repeat"));
2106 }
2107
TEST_F(StyleCascadeTest,MarkReferenced)2108 TEST_F(StyleCascadeTest, MarkReferenced) {
2109 RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
2110 RegisterProperty(GetDocument(), "--y", "<length>", "0px", false);
2111
2112 TestCascade cascade(GetDocument());
2113 cascade.Add("width", "var(--x)");
2114 cascade.Apply();
2115
2116 const auto* registry = GetDocument().GetPropertyRegistry();
2117 ASSERT_TRUE(registry);
2118
2119 EXPECT_TRUE(registry->WasReferenced("--x"));
2120 EXPECT_FALSE(registry->WasReferenced("--y"));
2121 }
2122
TEST_F(StyleCascadeTest,MarkHasVariableReferenceLonghand)2123 TEST_F(StyleCascadeTest, MarkHasVariableReferenceLonghand) {
2124 TestCascade cascade(GetDocument());
2125 cascade.Add("--x", "1px");
2126 cascade.Add("width", "var(--x)");
2127 cascade.Apply();
2128 auto style = cascade.TakeStyle();
2129 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2130 }
2131
TEST_F(StyleCascadeTest,MarkHasVariableReferenceShorthand)2132 TEST_F(StyleCascadeTest, MarkHasVariableReferenceShorthand) {
2133 TestCascade cascade(GetDocument());
2134 cascade.Add("--x", "1px");
2135 cascade.Add("margin", "var(--x)");
2136 cascade.Apply();
2137 auto style = cascade.TakeStyle();
2138 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2139 }
2140
TEST_F(StyleCascadeTest,MarkHasVariableReferenceLonghandMissingVar)2141 TEST_F(StyleCascadeTest, MarkHasVariableReferenceLonghandMissingVar) {
2142 TestCascade cascade(GetDocument());
2143 cascade.Add("width", "var(--x)");
2144 cascade.Apply();
2145 auto style = cascade.TakeStyle();
2146 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2147 }
2148
TEST_F(StyleCascadeTest,MarkHasVariableReferenceShorthandMissingVar)2149 TEST_F(StyleCascadeTest, MarkHasVariableReferenceShorthandMissingVar) {
2150 TestCascade cascade(GetDocument());
2151 cascade.Add("margin", "var(--x)");
2152 cascade.Apply();
2153 auto style = cascade.TakeStyle();
2154 EXPECT_TRUE(style->HasVariableReferenceFromNonInheritedProperty());
2155 }
2156
TEST_F(StyleCascadeTest,NoMarkHasVariableReferenceInherited)2157 TEST_F(StyleCascadeTest, NoMarkHasVariableReferenceInherited) {
2158 TestCascade cascade(GetDocument());
2159 cascade.Add("color", "var(--x)");
2160 cascade.Apply();
2161 auto style = cascade.TakeStyle();
2162 EXPECT_FALSE(style->HasVariableReferenceFromNonInheritedProperty());
2163 }
2164
TEST_F(StyleCascadeTest,NoMarkHasVariableReferenceWithoutVar)2165 TEST_F(StyleCascadeTest, NoMarkHasVariableReferenceWithoutVar) {
2166 TestCascade cascade(GetDocument());
2167 cascade.Add("width", "1px");
2168 cascade.Apply();
2169 auto style = cascade.TakeStyle();
2170 EXPECT_FALSE(style->HasVariableReferenceFromNonInheritedProperty());
2171 }
2172
TEST_F(StyleCascadeTest,InternalVisitedColorLonghand)2173 TEST_F(StyleCascadeTest, InternalVisitedColorLonghand) {
2174 TestCascade cascade(GetDocument());
2175 cascade.Add("color:green", CascadeOrigin::kAuthor);
2176 cascade.Add("color:red", CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
2177
2178 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
2179 cascade.Apply();
2180
2181 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2182
2183 Color red(255, 0, 0);
2184 const CSSProperty& color = GetCSSPropertyColor();
2185 EXPECT_EQ(red, cascade.TakeStyle()->VisitedDependentColor(color));
2186 }
2187
TEST_F(StyleCascadeTest,VarInInternalVisitedColorShorthand)2188 TEST_F(StyleCascadeTest, VarInInternalVisitedColorShorthand) {
2189 TestCascade cascade(GetDocument());
2190 cascade.Add("--x:red", CascadeOrigin::kAuthor);
2191 cascade.Add("outline:medium solid var(--x)", CascadeOrigin::kAuthor,
2192 CSSSelector::kMatchVisited);
2193 cascade.Add("outline-color:green", CascadeOrigin::kAuthor,
2194 CSSSelector::kMatchLink);
2195
2196 cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
2197 cascade.Apply();
2198
2199 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("outline-color"));
2200
2201 Color red(255, 0, 0);
2202 const CSSProperty& outline_color = GetCSSPropertyOutlineColor();
2203 EXPECT_EQ(red, cascade.TakeStyle()->VisitedDependentColor(outline_color));
2204 }
2205
TEST_F(StyleCascadeTest,ApplyWithFilter)2206 TEST_F(StyleCascadeTest, ApplyWithFilter) {
2207 TestCascade cascade(GetDocument());
2208 cascade.Add("color", "blue", Origin::kAuthor);
2209 cascade.Add("background-color", "green", Origin::kAuthor);
2210 cascade.Add("display", "inline", Origin::kAuthor);
2211 cascade.Apply();
2212 cascade.Add("color", "green", Origin::kAuthor);
2213 cascade.Add("background-color", "red", Origin::kAuthor);
2214 cascade.Add("display", "block", Origin::kAuthor);
2215 cascade.Apply(CascadeFilter(CSSProperty::kInherited, false));
2216 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2217 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("background-color"));
2218 EXPECT_EQ("inline", cascade.ComputedValue("display"));
2219 }
2220
TEST_F(StyleCascadeTest,HasAuthorBackground)2221 TEST_F(StyleCascadeTest, HasAuthorBackground) {
2222 Vector<String> properties = {"background-attachment"/*, "background-blend-mode",
2223 "background-clip", "background-image",
2224 "background-origin", "background-position-x",
2225 "background-position-y", "background-size"*/};
2226
2227 for (String property : properties) {
2228 TestCascade cascade(GetDocument());
2229 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
2230 cascade.Add(property, "unset", Origin::kAuthor);
2231 cascade.Apply();
2232 EXPECT_TRUE(cascade.TakeStyle()->HasAuthorBackground());
2233 }
2234 }
2235
TEST_F(StyleCascadeTest,HasAuthorBorder)2236 TEST_F(StyleCascadeTest, HasAuthorBorder) {
2237 Vector<String> properties = {
2238 "border-top-color", "border-right-color",
2239 "border-bottom-color", "border-left-color",
2240 "border-top-style", "border-right-style",
2241 "border-bottom-style", "border-left-style",
2242 "border-top-width", "border-right-width",
2243 "border-bottom-width", "border-left-width",
2244 "border-top-left-radius", "border-top-right-radius",
2245 "border-bottom-left-radius", "border-bottom-right-radius",
2246 "border-image-source", "border-image-slice",
2247 "border-image-width", "border-image-outset",
2248 "border-image-repeat"};
2249
2250 for (String property : properties) {
2251 TestCascade cascade(GetDocument());
2252 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
2253 cascade.Add(property, "unset", Origin::kAuthor);
2254 cascade.Apply();
2255 EXPECT_TRUE(cascade.TakeStyle()->HasAuthorBorder());
2256 }
2257 }
2258
TEST_F(StyleCascadeTest,NoAuthorBackgroundOrBorder)2259 TEST_F(StyleCascadeTest, NoAuthorBackgroundOrBorder) {
2260 TestCascade cascade(GetDocument());
2261 cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
2262 cascade.Add("background-color", "red", Origin::kUserAgent);
2263 cascade.Add("border-left-color", "green", Origin::kUserAgent);
2264 cascade.Add("background-clip", "padding-box", Origin::kUser);
2265 cascade.Add("border-right-color", "green", Origin::kUser);
2266 cascade.Apply();
2267 auto style = cascade.TakeStyle();
2268 EXPECT_FALSE(style->HasAuthorBackground());
2269 EXPECT_FALSE(style->HasAuthorBorder());
2270 }
2271
TEST_F(StyleCascadeTest,AnalyzeMatchResult)2272 TEST_F(StyleCascadeTest, AnalyzeMatchResult) {
2273 auto ua = CascadeOrigin::kUserAgent;
2274 auto author = CascadeOrigin::kAuthor;
2275
2276 TestCascade cascade(GetDocument());
2277 cascade.Add("display:none;left:5px", ua);
2278 cascade.Add("font-size:1px !important", ua);
2279 cascade.Add("display:block;color:red", author);
2280 cascade.Add("font-size:3px", author);
2281 cascade.Apply();
2282
2283 EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author);
2284 EXPECT_EQ(cascade.GetPriority("left").GetOrigin(), ua);
2285 EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), author);
2286 EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), ua);
2287 }
2288
TEST_F(StyleCascadeTest,AnalyzeMatchResultAll)2289 TEST_F(StyleCascadeTest, AnalyzeMatchResultAll) {
2290 auto ua = CascadeOrigin::kUserAgent;
2291 auto author = CascadeOrigin::kAuthor;
2292
2293 TestCascade cascade(GetDocument());
2294 cascade.Add("display:block", ua);
2295 cascade.Add("font-size:1px !important", ua);
2296 cascade.Add("all:unset", author);
2297 cascade.Apply();
2298
2299 EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author);
2300 EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), ua);
2301
2302 // Random sample from another property affected by 'all'.
2303 EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), author);
2304 EXPECT_EQ(cascade.GetPriority("color"), cascade.GetPriority("display"));
2305 }
2306
TEST_F(StyleCascadeTest,ApplyMatchResultFilter)2307 TEST_F(StyleCascadeTest, ApplyMatchResultFilter) {
2308 TestCascade cascade(GetDocument());
2309 cascade.Add("display:block");
2310 cascade.Add("color:green");
2311 cascade.Add("font-size:3px");
2312 cascade.Apply();
2313
2314 cascade.Add("display:inline");
2315 cascade.Add("color:red");
2316 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
2317
2318 EXPECT_EQ("inline", cascade.ComputedValue("display"));
2319 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2320 EXPECT_EQ("3px", cascade.ComputedValue("font-size"));
2321 }
2322
TEST_F(StyleCascadeTest,ApplyMatchResultAllFilter)2323 TEST_F(StyleCascadeTest, ApplyMatchResultAllFilter) {
2324 TestCascade cascade(GetDocument());
2325 cascade.Add("color:green");
2326 cascade.Add("display:block");
2327 cascade.Apply();
2328
2329 cascade.Add("all:unset");
2330 cascade.Apply(CascadeFilter(CSSProperty::kInherited, true));
2331
2332 EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color"));
2333 EXPECT_EQ("inline", cascade.ComputedValue("display"));
2334 }
2335
TEST_F(StyleCascadeTest,MarkHasReferenceLonghand)2336 TEST_F(StyleCascadeTest, MarkHasReferenceLonghand) {
2337 TestCascade cascade(GetDocument());
2338
2339 cascade.Add("--x:red");
2340 cascade.Add("background-color:var(--x)");
2341 cascade.Apply();
2342
2343 EXPECT_TRUE(cascade.State()
2344 .StyleRef()
2345 .HasVariableReferenceFromNonInheritedProperty());
2346 }
2347
TEST_F(StyleCascadeTest,MarkHasReferenceShorthand)2348 TEST_F(StyleCascadeTest, MarkHasReferenceShorthand) {
2349 TestCascade cascade(GetDocument());
2350
2351 cascade.Add("--x:red");
2352 cascade.Add("background:var(--x)");
2353 cascade.Apply();
2354
2355 EXPECT_TRUE(cascade.State()
2356 .StyleRef()
2357 .HasVariableReferenceFromNonInheritedProperty());
2358 }
2359
TEST_F(StyleCascadeTest,NoMarkHasReferenceForInherited)2360 TEST_F(StyleCascadeTest, NoMarkHasReferenceForInherited) {
2361 TestCascade cascade(GetDocument());
2362
2363 cascade.Add("--x:red");
2364 cascade.Add("--y:caption");
2365 cascade.Add("color:var(--x)");
2366 cascade.Add("font:var(--y)");
2367 cascade.Apply();
2368
2369 EXPECT_FALSE(cascade.State()
2370 .StyleRef()
2371 .HasVariableReferenceFromNonInheritedProperty());
2372 }
2373
TEST_F(StyleCascadeTest,Reset)2374 TEST_F(StyleCascadeTest, Reset) {
2375 TestCascade cascade(GetDocument());
2376
2377 EXPECT_EQ(CascadePriority(), cascade.GetPriority("color"));
2378 EXPECT_EQ(CascadePriority(), cascade.GetPriority("--x"));
2379
2380 cascade.Add("color:red");
2381 cascade.Add("--x:red");
2382 cascade.Apply(); // generation=1
2383 cascade.Apply(); // generation=2
2384
2385 EXPECT_EQ(2u, cascade.GetPriority("color").GetGeneration());
2386 EXPECT_EQ(2u, cascade.GetPriority("--x").GetGeneration());
2387
2388 cascade.Reset();
2389
2390 EXPECT_EQ(CascadePriority(), cascade.GetPriority("color"));
2391 EXPECT_EQ(CascadePriority(), cascade.GetPriority("--x"));
2392 }
2393
2394 } // namespace blink
2395