Skip to content

Commit

Permalink
Add correct equality testing for ComputedStyle's StyleVariableData
Browse files Browse the repository at this point in the history
objects.

This fixes the linked bug (large subtree style recalcs always when
using variables) and prevents a crash in release-with-asserts
builds that attempt to equality check the base style with a freshly
computed style during animations.

BUG=570176

Review URL: https://codereview.chromium.org/1537523003

Cr-Commit-Position: refs/heads/master@{#365814}
  • Loading branch information
shans authored and Commit bot committed Dec 17, 2015
1 parent 5c6bf86 commit b6cb0b1
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>

<style>
body {
--b: 420px;
}
#element {
--a: var(--b);
width: 100px;
height: 100px;
background-color: red;
transition: width 1s;
}

#element.triggered {
width: var(--a);
}
</style>

<div id='element'></div>

<script>
var test = async_test("this test passes if it doesn't assert");

requestAnimationFrame(x => {
element.classList.add('triggered');
requestAnimationFrame(x => {
requestAnimationFrame(x => {
requestAnimationFrame(x => {
requestAnimationFrame(x => {
test.done();
})
})
})
})
});
</script>
2 changes: 2 additions & 0 deletions third_party/WebKit/Source/core/core.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@
'style/StyleSelfAlignmentData.h',
'style/StyleSurroundData.cpp',
'style/StyleTransformData.cpp',
'style/StyleVariableData.cpp',
'style/StyleVariableData.h',
'style/StyleVisualData.cpp',
'style/StyleWillChangeData.cpp',
'layout/svg/line/SVGInlineFlowBox.cpp',
Expand Down
5 changes: 5 additions & 0 deletions third_party/WebKit/Source/core/css/CSSVariableData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ template<typename CharacterType> void CSSVariableData::updateTokens(const CSSPar
ASSERT(currentOffset == m_backingString.getCharacters<CharacterType>() + m_backingString.length());
}

bool CSSVariableData::operator==(const CSSVariableData& other) const
{
return tokens() == other.tokens();
}

void CSSVariableData::consumeAndUpdateTokens(const CSSParserTokenRange& range)
{
StringBuilder stringBuilder;
Expand Down
4 changes: 3 additions & 1 deletion third_party/WebKit/Source/core/css/CSSVariableData.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ class CSSVariableData : public RefCounted<CSSVariableData> {

CSSParserTokenRange tokenRange() { return m_tokens; }

const Vector<CSSParserToken>& tokens() { return m_tokens; }
const Vector<CSSParserToken>& tokens() const { return m_tokens; }

bool operator==(const CSSVariableData& other) const;

bool needsVariableResolution() const { return m_needsVariableResolution; }
private:
Expand Down
33 changes: 33 additions & 0 deletions third_party/WebKit/Source/core/css/parser/CSSParserToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,39 @@ class CORE_EXPORT CSSParserToken {

CSSParserToken(HashTokenType, CSSParserString);

bool operator==(const CSSParserToken& other) const
{
if (m_type != other.m_type)
return false;
switch (m_type) {
case DelimiterToken:
return delimiter() == other.delimiter();
case HashToken:
if (m_hashTokenType != other.m_hashTokenType)
return false;
// fallthrough
case IdentToken:
case FunctionToken:
case StringToken:
case UrlToken:
return m_valueDataCharRaw == other.m_valueDataCharRaw && m_valueLength == other.m_valueLength && m_valueIs8Bit == other.m_valueIs8Bit;
case NumberToken:
if (m_numericSign != other.m_numericSign)
return false;
// fallthrough
case DimensionToken:
if (m_valueDataCharRaw != other.m_valueDataCharRaw || m_valueLength != other.m_valueLength || m_valueIs8Bit != other.m_valueIs8Bit)
return false;
// fallthrough
case PercentageToken:
return m_numericValue == other.m_numericValue && m_numericValueType == other.m_numericValueType;
case UnicodeRangeToken:
return m_unicodeRange.start == other.m_unicodeRange.start && m_unicodeRange.end == other.m_unicodeRange.end;
default:
return true;
}
}

// Converts NumberToken to DimensionToken.
void convertToDimensionWithUnit(CSSParserString);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& m_rubyPosition == o.m_rubyPosition
&& dataEquivalent(listStyleImage.get(), o.listStyleImage.get())
&& dataEquivalent(appliedTextDecorations, o.appliedTextDecorations)
&& variables == o.variables;
&& dataEquivalent(variables, o.variables);
}

bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const
Expand Down
27 changes: 27 additions & 0 deletions third_party/WebKit/Source/core/style/StyleVariableData.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/style/StyleVariableData.h"

#include "core/style/DataEquivalency.h"

namespace blink {

bool StyleVariableData::operator==(const StyleVariableData& other) const
{
if (m_data.size() != other.m_data.size()) {
return false;
}

for (const auto& iter : m_data) {
RefPtr<CSSVariableData> otherData = other.m_data.get(iter.key);
if (!dataEquivalent(iter.value, otherData))
return false;
}

return true;
}

} // namespace blink
6 changes: 5 additions & 1 deletion third_party/WebKit/Source/core/style/StyleVariableData.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef StyleVariableData_h
#define StyleVariableData_h

Expand All @@ -14,7 +18,7 @@ class StyleVariableData : public RefCounted<StyleVariableData> {
static PassRefPtr<StyleVariableData> create() { return adoptRef(new StyleVariableData()); }
PassRefPtr<StyleVariableData> copy() const { return adoptRef(new StyleVariableData(*this)); }

bool operator==(const StyleVariableData& other) const { return other.m_data == m_data; }
bool operator==(const StyleVariableData& other) const;
bool operator!=(const StyleVariableData& other) const { return !(*this == other); }

void setVariable(const AtomicString& name, PassRefPtr<CSSVariableData> value) { m_data.set(name, value); }
Expand Down

0 comments on commit b6cb0b1

Please sign in to comment.