Bug 1273706 - Part 21: Have CSSVariableValues store more information. r?heycam
We store the parsed CSS value (for now, a placeholder -- in a later patch in
the series, we put all unregistered properties into token stream values and
typed properties into specified values of the appropriate type) as well as the
type (provided by ParseTypedValue) and the context of the declaration.
We also store a Maybe<CSSComputedValue> for computed registered custom
properties. The implementation for the computation of this is implemented in
later patches.
MozReview-Commit-ID: B8VBvHjwwyl
--- a/layout/style/CSSVariableResolver.cpp
+++ b/layout/style/CSSVariableResolver.cpp
@@ -123,18 +123,19 @@ CSSVariableResolver::RemoveCycles(size_t
}
void
CSSVariableResolver::ResolveVariable(size_t aID)
{
if (mVariables[aID].mValue.IsEmpty() || mVariables[aID].mWasInherited) {
// The variable is invalid or was inherited. We can just copy the value
// and its first/last token information across.
- mOutput->Put(mVariables[aID].mVariableName,
- mVariables[aID].mValue,
+ mOutput->Put(mVariables[aID].mVariableName, mVariables[aID].mValue,
+ // Replaced by a later patch in the series.
+ nsCSSValue(), CSSValueType(), CSSVariableExprContext(),
mVariables[aID].mFirstToken,
mVariables[aID].mLastToken);
} else {
// Otherwise we need to resolve the variable references, after resolving
// all of our dependencies first. We do this even for variables that we
// know do not reference other variables so that we can find their
// first/last token.
//
@@ -149,17 +150,20 @@ CSSVariableResolver::ResolveVariable(siz
}
nsString resolvedValue;
nsCSSTokenSerializationType firstToken, lastToken;
if (!mParser.ResolveVariableValue(mVariables[aID].mValue, mOutput,
resolvedValue, firstToken, lastToken)) {
resolvedValue.Truncate(0);
}
mOutput->Put(mVariables[aID].mVariableName, resolvedValue,
+ // Replaced by a later patch in the series.
+ nsCSSValue(), CSSValueType(), CSSVariableExprContext(),
firstToken, lastToken);
+
}
mVariables[aID].mResolved = true;
}
void
CSSVariableResolver::Resolve(const CSSVariableValues* aInherited,
const CSSVariableDeclarations* aSpecified)
{
--- a/layout/style/CSSVariableValues.cpp
+++ b/layout/style/CSSVariableValues.cpp
@@ -1,18 +1,18 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* computed CSS Variable values */
-#include "CSSVariableValues.h"
+#include "mozilla/CSSVariableValues.h"
-#include "CSSVariableResolver.h"
+#include "mozilla/CSSVariableResolver.h"
namespace mozilla {
CSSVariableValues::CSSVariableValues()
{
MOZ_COUNT_CTOR(CSSVariableValues);
}
@@ -50,98 +50,114 @@ CSSVariableValues::operator==(const CSSV
}
for (size_t thisIndex = 0; thisIndex < mVariables.Length(); ++thisIndex) {
size_t otherIndex;
if (!aOther.mVariableIDs.Get(mVariables[thisIndex].mVariableName,
&otherIndex)) {
return false;
}
- const nsString& otherValue = aOther.mVariables[otherIndex].mValue;
- if (!mVariables[thisIndex].mValue.Equals(otherValue)) {
+ const nsString& otherExpr = aOther.mVariables[otherIndex].mExpr;
+ if (!mVariables[thisIndex].mExpr.Equals(otherExpr)) {
return false;
}
}
return true;
}
size_t
CSSVariableValues::Count() const
{
return mVariables.Length();
}
bool
-CSSVariableValues::Get(const nsAString& aName, nsString& aValue) const
+CSSVariableValues::Get(const nsAString& aName, nsAString& aExpr) const
{
size_t id;
if (!mVariableIDs.Get(aName, &id)) {
return false;
}
- aValue = mVariables[id].mValue;
+ aExpr = mVariables[id].mExpr;
return true;
}
bool
CSSVariableValues::Get(const nsAString& aName,
- nsString& aValue,
+ nsString& aExpr, nsCSSValue& aValue, CSSValueType& aType,
+ CSSVariableExprContext& aContext,
nsCSSTokenSerializationType& aFirstToken,
nsCSSTokenSerializationType& aLastToken) const
{
size_t id;
if (!mVariableIDs.Get(aName, &id)) {
return false;
}
+ aExpr = mVariables[id].mExpr;
aValue = mVariables[id].mValue;
+ aType = mVariables[id].mType;
+ aContext = mVariables[id].mContext;
aFirstToken = mVariables[id].mFirstToken;
aLastToken = mVariables[id].mLastToken;
return true;
}
+bool
+CSSVariableValues::Has(const nsAString& aName) const
+{
+ return mVariableIDs.Get(aName, nullptr);
+}
+
void
CSSVariableValues::GetVariableAt(size_t aIndex, nsAString& aName) const
{
aName = mVariables[aIndex].mVariableName;
}
void
-CSSVariableValues::Put(const nsAString& aName,
- nsString aValue,
+CSSVariableValues::Put(const nsAString& aName, nsString aExpr,
+ nsCSSValue aValue, CSSValueType aType,
+ CSSVariableExprContext aContext,
nsCSSTokenSerializationType aFirstToken,
nsCSSTokenSerializationType aLastToken)
{
size_t id;
if (mVariableIDs.Get(aName, &id)) {
+ mVariables[id].mExpr = aExpr;
mVariables[id].mValue = aValue;
+ mVariables[id].mType = aType;
+ mVariables[id].mContext = aContext;
mVariables[id].mFirstToken = aFirstToken;
mVariables[id].mLastToken = aLastToken;
} else {
id = mVariables.Length();
mVariableIDs.Put(aName, id);
- mVariables.AppendElement(Variable(aName, aValue, aFirstToken, aLastToken));
+ mVariables.AppendElement(Variable(aName, aExpr, aValue, aType, aContext,
+ aFirstToken, aLastToken));
}
}
void
CSSVariableValues::CopyVariablesFrom(const CSSVariableValues& aOther)
{
for (size_t i = 0, n = aOther.mVariables.Length(); i < n; i++) {
Put(aOther.mVariables[i].mVariableName,
+ aOther.mVariables[i].mExpr,
aOther.mVariables[i].mValue,
+ aOther.mVariables[i].mType,
+ aOther.mVariables[i].mContext,
aOther.mVariables[i].mFirstToken,
aOther.mVariables[i].mLastToken);
}
}
void
CSSVariableValues::AddVariablesToResolver(CSSVariableResolver* aResolver) const
{
for (size_t i = 0, n = mVariables.Length(); i < n; i++) {
- aResolver->Put(mVariables[i].mVariableName,
- mVariables[i].mValue,
- mVariables[i].mFirstToken,
- mVariables[i].mLastToken,
- true);
+ // Replaced by a later patch in the series.
+ aResolver->Put(mVariables[i].mVariableName, mVariables[i].mExpr,
+ mVariables[i].mFirstToken, mVariables[i].mLastToken, true);
}
}
} // namespace mozilla
--- a/layout/style/CSSVariableValues.h
+++ b/layout/style/CSSVariableValues.h
@@ -3,17 +3,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* computed CSS Variable values */
#ifndef mozilla_CSSVariableValues_h
#define mozilla_CSSVariableValues_h
+#include "mozilla/CSSComputedValue.h"
+#include "mozilla/CSSValueType.h"
+#include "mozilla/CSSVariableRegistration.h"
#include "nsCSSScanner.h"
+#include "nsCSSValue.h"
#include "nsDataHashtable.h"
#include "nsTArray.h"
namespace mozilla {
class CSSVariableResolver;
class CSSVariableValues
@@ -30,42 +34,50 @@ public:
bool operator!=(const CSSVariableValues& aOther) const
{ return !(*this == aOther); }
/**
* Gets the value of a variable in this set of computed variables.
*
* @param aName The variable name (not including any "--" prefix that would
* be part of the custom property name).
- * @param aValue Out parameter into which the value of the variable will
+ * @param aExpr Out parameter into which the expression of the variable will
* be stored.
* @return Whether a variable with the given name was found. When false
- * is returned, aValue will not be modified.
+ * is returned, aExpr will not be modified.
*/
- bool Get(const nsAString& aName, nsString& aValue) const;
+ bool Get(const nsAString& aName, nsAString& aExpr) const;
/**
* Gets the value of a variable in this set of computed variables, along
* with information on the types of tokens that appear at the start and
* end of the token stream.
*
* @param aName The variable name (not including any "--" prefix that would
* be part of the custom property name).
- * @param aValue Out parameter into which the value of the variable will
+ * @param aExpr Out parameter into which the expression of the variable will
+ * be stored.
+ * @param aValue Out parameter into which the nsCSSValue of the variable will
* be stored.
+ * @param aType Out parameter into which the type of the value will be
+ * stored.
+ * @param aContext Out parameter into which the context of the variable
+ * declaration will be stored.
* @param aFirstToken The type of token at the start of the variable value.
* @param aLastToken The type of token at the en of the variable value.
* @return Whether a variable with the given name was found. When false
* is returned, aValue, aFirstToken and aLastToken will not be modified.
*/
- bool Get(const nsAString& aName,
- nsString& aValue,
+ bool Get(const nsAString& aName, nsString& aExpr, nsCSSValue& aValue,
+ CSSValueType& aType, CSSVariableExprContext& aContext,
nsCSSTokenSerializationType& aFirstToken,
nsCSSTokenSerializationType& aLastToken) const;
+ bool Has(const nsAString& aName) const;
+
/**
* Gets the name of the variable at the given index.
*
* Variables on this object are ordered, and that order is just determined
* based on the order that they are added to the object. A consistent
* ordering is required for CSSDeclaration objects in the DOM.
* CSSDeclarations expose property names as indexed properties, which need to
* be stable.
@@ -81,51 +93,66 @@ public:
*/
size_t Count() const;
/**
* Adds or modifies an existing entry in this set of variable values.
*
* @param aName The variable name (not including any "--" prefix that would
* be part of the custom property name) whose value is to be set.
+ * @param aExpr The variable expression.
* @param aValue The variable value.
+ * @param aType The variable type.
+ * @param aContext The variable context.
* @param aFirstToken The type of token at the start of the variable value.
* @param aLastToken The type of token at the en of the variable value.
*/
- void Put(const nsAString& aName,
- nsString aValue,
+ void Put(const nsAString& aName, nsString aExpr, nsCSSValue aValue,
+ CSSValueType aType, CSSVariableExprContext aContext,
nsCSSTokenSerializationType aFirstToken,
nsCSSTokenSerializationType aLastToken);
/**
* Copies the variables from this object into aResolver, marking them as
* computed, inherited values.
*/
void AddVariablesToResolver(CSSVariableResolver* aResolver) const;
private:
struct Variable
{
- Variable()
- : mFirstToken(eCSSTokenSerialization_Nothing)
+ explicit Variable(CSSVariableExprContext aContext)
+ : mContext(aContext)
+ , mFirstToken(eCSSTokenSerialization_Nothing)
, mLastToken(eCSSTokenSerialization_Nothing)
{}
Variable(const nsAString& aVariableName,
- nsString aValue,
+ nsString aExpr,
+ nsCSSValue aValue,
+ CSSValueType aType,
+ CSSVariableExprContext aContext,
nsCSSTokenSerializationType aFirstToken,
nsCSSTokenSerializationType aLastToken)
: mVariableName(aVariableName)
+ , mExpr(aExpr)
, mValue(aValue)
+ , mType(aType)
+ , mContext(aContext)
, mFirstToken(aFirstToken)
, mLastToken(aLastToken)
{}
nsString mVariableName;
- nsString mValue;
+
+ nsString mExpr;
+ nsCSSValue mValue;
+ CSSValueType mType;
+ CSSVariableExprContext mContext;
+
nsCSSTokenSerializationType mFirstToken;
nsCSSTokenSerializationType mLastToken;
};
/**
* Adds all the variables from aOther into this object.
*/
void CopyVariablesFrom(const CSSVariableValues& aOther);
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -2781,45 +2781,49 @@ CSSParserImpl::ResolveValueWithVariableR
EqualsLiteral("--"));
nsDependentString variableName(mToken.mIdent,
CSS_CUSTOM_NAME_PREFIX_LENGTH);
// Get the value of the identified variable. Note that we
// check if the variable value is the empty string, as that means
// that the variable was invalid at computed value time due to
// unresolveable variable references or cycles.
- nsString variableValue;
+ nsString varExpr;
+ nsCSSValue varValue;
+ CSSValueType varType;
+ CSSVariableExprContext varContext;
nsCSSTokenSerializationType varFirstToken, varLastToken;
- bool valid = aVariables->Get(variableName, variableValue,
- varFirstToken, varLastToken) &&
- !variableValue.IsEmpty();
+ bool valid = aVariables->Get(variableName, varExpr, varValue,
+ varType, varContext, varFirstToken,
+ varLastToken) &&
+ !varExpr.IsEmpty();
if (!GetToken(true) ||
mToken.IsSymbol(')')) {
mScanner->StartRecording();
if (!valid) {
// Invalid variable with no fallback.
return false;
}
// Valid variable with no fallback.
AppendTokens(value, valueFirstToken, valueLastToken,
- varFirstToken, varLastToken, variableValue);
+ varFirstToken, varLastToken, varExpr);
} else if (mToken.IsSymbol(',')) {
mScanner->StartRecording();
if (!GetToken(false) ||
mToken.IsSymbol(')')) {
// Comma must be followed by at least one fallback token.
return false;
}
UngetToken();
if (valid) {
// Valid variable with ignored fallback.
mScanner->StopRecording();
AppendTokens(value, valueFirstToken, valueLastToken,
- varFirstToken, varLastToken, variableValue);
+ varFirstToken, varLastToken, varExpr);
bool ok = SkipBalancedContentUntil(')');
mScanner->StartRecording();
if (!ok) {
return false;
}
} else {
nsString fallback;
if (!ResolveValueWithVariableReferencesRec(fallback,