예제 #1
0
TEST_F(StyleEngineTest, AnalyzedInject) {
  document().body()->setInnerHTML(
      "<style>div { color: red }</style><div id='t1'>Green</div><div></div>");
  document().view()->updateAllLifecyclePhases();

  Element* t1 = document().getElementById("t1");
  ASSERT_TRUE(t1);
  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(255, 0, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));

  unsigned beforeCount = styleEngine().styleForElementCount();

  StyleSheetContents* parsedSheet =
      StyleSheetContents::create(CSSParserContext(document(), nullptr));
  parsedSheet->parseString("#t1 { color: green }");
  styleEngine().injectAuthorSheet(parsedSheet);
  document().view()->updateAllLifecyclePhases();

  unsigned afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(1u, afterCount - beforeCount);

  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(0, 128, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));
}
예제 #2
0
TEST_F(StyleEngineTest, RuleSetInvalidationHostContext) {
  document().body()->setInnerHTML("<div id=host></div>");
  Element* host = document().getElementById("host");
  ASSERT_TRUE(host);

  ShadowRootInit init;
  init.setMode("open");
  ShadowRoot* shadowRoot = host->attachShadow(
      ScriptState::forMainWorld(document().frame()), init, ASSERT_NO_EXCEPTION);
  ASSERT_TRUE(shadowRoot);

  shadowRoot->setInnerHTML("<div></div><div class=a></div><div></div>");
  document().view()->updateAllLifecyclePhases();

  unsigned beforeCount = styleEngine().styleForElementCount();
  EXPECT_EQ(scheduleInvalidationsForRules(
                *shadowRoot, ":host-context(.nomatch) .a { background: green}"),
            RuleSetInvalidationsScheduled);
  document().view()->updateAllLifecyclePhases();
  unsigned afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(1u, afterCount - beforeCount);

  EXPECT_EQ(scheduleInvalidationsForRules(
                *shadowRoot, ":host-context(:hover) { background: green}"),
            RuleSetInvalidationFullRecalc);
  EXPECT_EQ(scheduleInvalidationsForRules(
                *shadowRoot, ":host-context(#host) { background: green}"),
            RuleSetInvalidationFullRecalc);
}
예제 #3
0
TEST_F(StyleEngineTest, StyleMediaAttributeNoStyleChange) {
  document().body()->setInnerHTML(
      "<style id='s1' media='(max-width: 1000px)'>#t1 { color: green }</style>"
      "<div id='t1'>Green</div><div></div>");
  document().view()->updateAllLifecyclePhases();

  Element* t1 = document().getElementById("t1");
  ASSERT_TRUE(t1);
  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(0, 128, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));

  unsigned beforeCount = styleEngine().styleForElementCount();

  Element* s1 = document().getElementById("s1");
  s1->setAttribute(blink::HTMLNames::mediaAttr, "(max-width: 2000px)");
  document().view()->updateAllLifecyclePhases();

  unsigned afterCount = styleEngine().styleForElementCount();
  // TODO([email protected]): Should be 0 for ruleset based invalidations.
  EXPECT_EQ(8u, afterCount - beforeCount);

  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(0, 128, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));
}
예제 #4
0
TEST_F(StyleEngineTest, RuleSetInvalidationTypeSelectors) {
  document().body()->setInnerHTML(
      "<div>"
      "  <span></span>"
      "  <div></div>"
      "</div>");

  document().view()->updateAllLifecyclePhases();

  unsigned beforeCount = styleEngine().styleForElementCount();
  EXPECT_EQ(
      scheduleInvalidationsForRules(document(), "span { background: green}"),
      RuleSetInvalidationsScheduled);
  document().view()->updateAllLifecyclePhases();
  unsigned afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(1u, afterCount - beforeCount);

  beforeCount = afterCount;
  EXPECT_EQ(scheduleInvalidationsForRules(document(),
                                          "body div { background: green}"),
            RuleSetInvalidationsScheduled);
  document().view()->updateAllLifecyclePhases();
  afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(2u, afterCount - beforeCount);

  EXPECT_EQ(
      scheduleInvalidationsForRules(document(), "div * { background: green}"),
      RuleSetInvalidationFullRecalc);
}
예제 #5
0
TEST_F(CSSSelectorWatchTest, RecalcOnDocumentChange) {
  document().body()->setInnerHTML(
      "<div>"
      "  <span id='x' class='a'></span>"
      "  <span id='y' class='b'><span></span></span>"
      "  <span id='z'><span></span></span>"
      "</div>",
      ASSERT_NO_EXCEPTION);

  CSSSelectorWatch& watch = CSSSelectorWatch::from(document());

  Vector<String> selectors;
  selectors.append(".a");
  watch.watchCSSSelectors(selectors);

  document().view()->updateAllLifecyclePhases();

  selectors.clear();
  selectors.append(".b");
  selectors.append(".c");
  selectors.append("#nomatch");
  watch.watchCSSSelectors(selectors);

  document().view()->updateAllLifecyclePhases();

  Element* x = document().getElementById("x");
  Element* y = document().getElementById("y");
  Element* z = document().getElementById("z");
  ASSERT_TRUE(x);
  ASSERT_TRUE(y);
  ASSERT_TRUE(z);

  x->removeAttribute(HTMLNames::classAttr);
  y->removeAttribute(HTMLNames::classAttr);
  z->setAttribute(HTMLNames::classAttr, "c");

  clearAddedRemoved(watch);

  unsigned beforeCount = styleEngine().styleForElementCount();
  document().view()->updateAllLifecyclePhases();
  unsigned afterCount = styleEngine().styleForElementCount();

  EXPECT_EQ(2u, afterCount - beforeCount);

  EXPECT_EQ(1u, addedSelectors(watch).size());
  EXPECT_TRUE(addedSelectors(watch).contains(".c"));

  EXPECT_EQ(1u, removedSelectors(watch).size());
  EXPECT_TRUE(removedSelectors(watch).contains(".b"));
}
예제 #6
0
TEST_F(StyleEngineTest, DocumentDirtyAfterInject) {
  StyleSheetContents* parsedSheet =
      StyleSheetContents::create(CSSParserContext(document(), nullptr));
  parsedSheet->parseString("div {}");
  styleEngine().injectAuthorSheet(parsedSheet);
  document().view()->updateAllLifecyclePhases();

  EXPECT_TRUE(isDocumentStyleSheetCollectionClean());
}
예제 #7
0
TEST_F(ApplyRulesetsTest, AddShadowV0BoundaryCrossingRuleToDocument) {
  document().view()->updateAllLifecyclePhases();

  CSSStyleSheet* sheet = createSheet(".a /deep/ .b { color:red }");

  ActiveStyleSheetVector newStyleSheets;
  newStyleSheets.append(std::make_pair(sheet, &sheet->contents()->ruleSet()));

  applyRuleSetChanges(styleEngine(), document(), ActiveStyleSheetVector(),
                      newStyleSheets);

  EXPECT_EQ(SubtreeStyleChange, document().getStyleChangeType());
}
예제 #8
0
TEST_F(ApplyRulesetsTest, AddFontFaceRuleToDocument) {
  document().view()->updateAllLifecyclePhases();

  CSSStyleSheet* sheet =
      createSheet("@font-face { font-family: ahum; src: url(ahum.ttf) }");

  ActiveStyleSheetVector newStyleSheets;
  newStyleSheets.append(std::make_pair(sheet, &sheet->contents()->ruleSet()));

  applyRuleSetChanges(styleEngine(), document(), ActiveStyleSheetVector(),
                      newStyleSheets);

  EXPECT_EQ(SubtreeStyleChange, document().getStyleChangeType());
}
예제 #9
0
TEST_F(StyleEngineTest, RuleSetInvalidationSlotted) {
  document().body()->setInnerHTML(
      "<div id=host>"
      "  <span slot=other class=s1></span>"
      "  <span class=s2></span>"
      "  <span class=s1></span>"
      "  <span></span>"
      "</div>");

  Element* host = document().getElementById("host");
  ASSERT_TRUE(host);

  ShadowRootInit init;
  init.setMode("open");
  ShadowRoot* shadowRoot = host->attachShadow(
      ScriptState::forMainWorld(document().frame()), init, ASSERT_NO_EXCEPTION);
  ASSERT_TRUE(shadowRoot);

  shadowRoot->setInnerHTML("<slot name=other></slot><slot></slot>");
  document().view()->updateAllLifecyclePhases();

  unsigned beforeCount = styleEngine().styleForElementCount();
  EXPECT_EQ(scheduleInvalidationsForRules(
                *shadowRoot, "::slotted(.s1) { background: green}"),
            RuleSetInvalidationsScheduled);
  document().view()->updateAllLifecyclePhases();
  unsigned afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(4u, afterCount - beforeCount);

  beforeCount = afterCount;
  EXPECT_EQ(scheduleInvalidationsForRules(*shadowRoot,
                                          "::slotted(*) { background: green}"),
            RuleSetInvalidationsScheduled);
  document().view()->updateAllLifecyclePhases();
  afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(4u, afterCount - beforeCount);
}
예제 #10
0
TEST_F(StyleEngineTest, TextToSheetCache) {
  HTMLStyleElement* element = HTMLStyleElement::create(document(), false);

  String sheetText("div {}");
  TextPosition minPos = TextPosition::minimumPosition();
  StyleEngineContext context;

  CSSStyleSheet* sheet1 =
      styleEngine().createSheet(*element, sheetText, minPos, context);

  // Check that the first sheet is not using a cached StyleSheetContents.
  EXPECT_FALSE(sheet1->contents()->isUsedFromTextCache());

  CSSStyleSheet* sheet2 =
      styleEngine().createSheet(*element, sheetText, minPos, context);

  // Check that the second sheet uses the cached StyleSheetContents for the
  // first.
  EXPECT_EQ(sheet1->contents(), sheet2->contents());
  EXPECT_TRUE(sheet2->contents()->isUsedFromTextCache());

  sheet1 = nullptr;
  sheet2 = nullptr;
  element = nullptr;

  // Garbage collection should clear the weak reference in the
  // StyleSheetContents cache.
  ThreadState::current()->collectAllGarbage();

  element = HTMLStyleElement::create(document(), false);
  sheet1 = styleEngine().createSheet(*element, sheetText, minPos, context);

  // Check that we did not use a cached StyleSheetContents after the garbage
  // collection.
  EXPECT_FALSE(sheet1->contents()->isUsedFromTextCache());
}
예제 #11
0
StyleEngineTest::RuleSetInvalidation
StyleEngineTest::scheduleInvalidationsForRules(TreeScope& treeScope,
                                               const String& cssText) {
  StyleSheetContents* sheet =
      StyleSheetContents::create(CSSParserContext(HTMLStandardMode, nullptr));
  sheet->parseString(cssText);
  HeapVector<Member<RuleSet>> ruleSets;
  RuleSet& ruleSet = sheet->ensureRuleSet(MediaQueryEvaluator(),
                                          RuleHasDocumentSecurityOrigin);
  ruleSet.compactRulesIfNeeded();
  if (ruleSet.needsFullRecalcForRuleSetInvalidation())
    return RuleSetInvalidationFullRecalc;
  ruleSets.append(&ruleSet);
  styleEngine().scheduleInvalidationsForRuleSets(treeScope, ruleSets);
  return RuleSetInvalidationsScheduled;
}
예제 #12
0
TEST_F(ApplyRulesetsTest, AddFontFaceRuleToShadowTree) {
  document().body()->setInnerHTML("<div id=host></div>", ASSERT_NO_EXCEPTION);
  Element* host = document().getElementById("host");
  ASSERT_TRUE(host);

  ShadowRoot& shadowRoot = attachShadow(*host);
  document().view()->updateAllLifecyclePhases();

  CSSStyleSheet* sheet =
      createSheet("@font-face { font-family: ahum; src: url(ahum.ttf) }");

  ActiveStyleSheetVector newStyleSheets;
  newStyleSheets.append(std::make_pair(sheet, &sheet->contents()->ruleSet()));

  applyRuleSetChanges(styleEngine(), shadowRoot, ActiveStyleSheetVector(),
                      newStyleSheets);

  EXPECT_FALSE(document().needsLayoutTreeUpdate());
}
예제 #13
0
TEST_F(ApplyRulesetsTest, AddShadowV0BoundaryCrossingRuleToShadowTree) {
  document().body()->setInnerHTML("<div id=host></div>", ASSERT_NO_EXCEPTION);
  Element* host = document().getElementById("host");
  ASSERT_TRUE(host);

  ShadowRoot& shadowRoot = attachShadow(*host);
  document().view()->updateAllLifecyclePhases();

  CSSStyleSheet* sheet = createSheet(".a /deep/ .b { color:red }");

  ActiveStyleSheetVector newStyleSheets;
  newStyleSheets.append(std::make_pair(sheet, &sheet->contents()->ruleSet()));

  applyRuleSetChanges(styleEngine(), shadowRoot, ActiveStyleSheetVector(),
                      newStyleSheets);

  EXPECT_FALSE(document().needsStyleRecalc());
  EXPECT_EQ(SubtreeStyleChange, host->getStyleChangeType());
}
예제 #14
0
 bool isDocumentStyleSheetCollectionClean() {
   return !styleEngine().shouldUpdateDocumentStyleSheetCollection();
 }