Bug 1231682 part 1: When nsCSSParser is parsing a property-alias, keep track of the alias in a member-var. r=heycam
MozReview-Commit-ID: 6kKrOQsfWnW
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -361,18 +361,28 @@ public:
enabledState |= nsCSSProps::eEnabledInUASheets;
}
if (mIsChrome) {
enabledState |= nsCSSProps::eEnabledInChrome;
}
return enabledState;
}
- nsCSSProperty LookupEnabledProperty(const nsAString& aProperty) {
- return nsCSSProps::LookupProperty(aProperty, PropertyEnabledState());
+ nsCSSProperty LookupEnabledProperty(const nsAString& aProperty,
+ nsCSSProperty* aAliasPropID) {
+ nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty,
+ PropertyEnabledState(),
+ aAliasPropID);
+ MOZ_ASSERT(!aAliasPropID ||
+ *aAliasPropID == eCSSProperty_UNKNOWN ||
+ (*aAliasPropID >= eCSSProperty_COUNT &&
+ *aAliasPropID < eCSSProperty_COUNT_with_aliases),
+ "Outparam *aAliasPropID should end up UNKNOWN or a valid alias");
+
+ return propID;
}
protected:
class nsAutoParseCompoundProperty;
friend class nsAutoParseCompoundProperty;
class nsAutoFailingSupportsRule;
friend class nsAutoFailingSupportsRule;
@@ -1355,16 +1365,23 @@ protected:
RefPtr<CSSStyleSheet> mSheet;
// Used for @import rules
css::Loader* mChildLoader; // not ref counted, it owns us
// Any sheets we may reuse when parsing an @import.
css::LoaderReusableStyleSheets* mReusableSheets;
+ // If we're parsing a property-alias, this variable should be set to the ID
+ // of the alias for the duration of the parse operation. (Generally, wherever
+ // we call LookupEnabledProperty() followed by ParseProperty(), this variable
+ // should be set between those two calls & should be cleared after
+ // ParseProperty() completes).
+ nsCSSProperty mAliasBeingParsed;
+
// Sheet section we're in. This is used to enforce correct ordering of the
// various rule types (eg the fact that a @charset rule must come before
// anything else). Note that there are checks of similar things in various
// places in CSSStyleSheet.cpp (e.g in insertRule, RebuildChildList).
enum nsCSSSection {
eCSSSection_Charset,
eCSSSection_Import,
eCSSSection_NameSpace,
@@ -1511,16 +1528,17 @@ static void AppendRuleToSheet(css::Rule*
mReporter->ClearError()
CSSParserImpl::CSSParserImpl()
: mToken(),
mScanner(nullptr),
mReporter(nullptr),
mChildLoader(nullptr),
mReusableSheets(nullptr),
+ mAliasBeingParsed(eCSSProperty_UNKNOWN),
mSection(eCSSSection_Charset),
mNameSpaceMap(nullptr),
mHavePushBack(false),
mNavQuirkMode(false),
mHashlessColorQuirk(false),
mUnitlessLengthQuirk(false),
mParsingMode(css::eAuthorSheetFeatures),
mIsChrome(false),
@@ -2297,17 +2315,18 @@ CSSParserImpl::ParseKeyframeSelectorStri
bool
CSSParserImpl::EvaluateSupportsDeclaration(const nsAString& aProperty,
const nsAString& aValue,
nsIURI* aDocURL,
nsIURI* aBaseURL,
nsIPrincipal* aDocPrincipal)
{
- nsCSSProperty propID = LookupEnabledProperty(aProperty);
+ nsCSSProperty aliasPropID;
+ nsCSSProperty propID = LookupEnabledProperty(aProperty, &aliasPropID);
if (propID == eCSSProperty_UNKNOWN) {
return false;
}
nsCSSScanner scanner(aValue, 0);
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aDocURL);
InitScanner(scanner, reporter, aDocURL, aBaseURL, aDocPrincipal);
nsAutoSuppressErrors suppressErrors(this);
@@ -2319,16 +2338,20 @@ CSSParserImpl::EvaluateSupportsDeclarati
CSS_CUSTOM_NAME_PREFIX_LENGTH).EqualsLiteral("--"));
const nsDependentSubstring varName =
Substring(aProperty, CSS_CUSTOM_NAME_PREFIX_LENGTH); // remove '--'
CSSVariableDeclarations::Type variableType;
nsString variableValue;
parsedOK = ParseVariableDeclaration(&variableType, variableValue) &&
!GetToken(true);
} else {
+ AutoRestore<nsCSSProperty> autoRestore(mAliasBeingParsed);
+ if (aliasPropID != eCSSProperty_UNKNOWN) {
+ mAliasBeingParsed = aliasPropID;
+ }
parsedOK = ParseProperty(propID) && !GetToken(true);
mTempData.ClearProperty(propID);
mTempData.AssertInitialState();
}
CLEAR_ERROR();
ReleaseScanner();
@@ -4586,17 +4609,18 @@ CSSParserImpl::ParseSupportsConditionInP
if (mToken.mType == eCSSToken_Ident) {
if (!mToken.mIdent.LowerCaseEqualsLiteral("not")) {
nsAutoString propertyName = mToken.mIdent;
if (!ExpectSymbol(':', true)) {
return false;
}
- nsCSSProperty propID = LookupEnabledProperty(propertyName);
+ nsCSSProperty aliasPropID;
+ nsCSSProperty propID = LookupEnabledProperty(propertyName, &aliasPropID);
if (propID == eCSSProperty_UNKNOWN) {
if (ExpectSymbol(')', true)) {
UngetToken();
return false;
}
aConditionMet = false;
SkipUntil(')');
UngetToken();
@@ -4614,16 +4638,20 @@ CSSParserImpl::ParseSupportsConditionInP
SkipUntil(')');
UngetToken();
}
} else {
if (ExpectSymbol(')', true)) {
UngetToken();
return false;
}
+ AutoRestore<nsCSSProperty> autoRestore(mAliasBeingParsed);
+ if (aliasPropID != eCSSProperty_UNKNOWN) {
+ mAliasBeingParsed = aliasPropID;
+ }
aConditionMet = ParseProperty(propID) &&
ParsePriority() != ePriority_Error;
if (!aConditionMet) {
SkipUntil(')');
UngetToken();
}
mTempData.ClearProperty(propID);
mTempData.AssertInitialState();
@@ -7185,17 +7213,19 @@ CSSParserImpl::ParseDeclaration(css::Dec
if (!ParseVariableDeclaration(&variableType, variableValue)) {
REPORT_UNEXPECTED_P(PEValueParsingError, propertyName);
REPORT_UNEXPECTED(PEDeclDropped);
OUTPUT_ERROR();
return false;
}
} else {
// Map property name to its ID.
- propID = LookupEnabledProperty(propertyName);
+ nsCSSProperty aliasPropID;
+ propID = LookupEnabledProperty(propertyName, &aliasPropID);
+
if (eCSSProperty_UNKNOWN == propID ||
eCSSPropertyExtra_variable == propID ||
(aContext == eCSSContext_Page &&
!nsCSSProps::PropHasFlags(propID,
CSS_PROPERTY_APPLIES_TO_PAGE_RULE))) { // unknown property
if (NonMozillaVendorIdentifier(propertyName)) {
if (!mInSupportsCondition &&
aContext == eCSSContext_General &&
@@ -7210,16 +7240,24 @@ CSSParserImpl::ParseDeclaration(css::Dec
}
} else {
REPORT_UNEXPECTED_P(PEUnknownProperty, propertyName);
REPORT_UNEXPECTED(PEDeclDropped);
OUTPUT_ERROR();
}
return false;
}
+
+ MOZ_ASSERT(mAliasBeingParsed == eCSSProperty_UNKNOWN,
+ "Someone forgot to clear mAliasBeingParsed");
+ AutoRestore<nsCSSProperty> autoRestore(mAliasBeingParsed);
+ if (aliasPropID != eCSSProperty_UNKNOWN) {
+ mAliasBeingParsed = aliasPropID;
+ }
+
// Then parse the property.
if (!ParseProperty(propID)) {
// XXX Much better to put stuff in the value parsers instead...
REPORT_UNEXPECTED_P(PEValueParsingError, propertyName);
REPORT_UNEXPECTED(PEDeclDropped);
OUTPUT_ERROR();
mTempData.ClearProperty(propID);
mTempData.AssertInitialState();
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -515,20 +515,25 @@ nsCSSProps::IsCustomPropertyName(const n
nsCSSProps::IsCustomPropertyName(const nsAString& aProperty)
{
return aProperty.Length() >= CSS_CUSTOM_NAME_PREFIX_LENGTH &&
StringBeginsWith(aProperty, NS_LITERAL_STRING("--"));
}
nsCSSProperty
nsCSSProps::LookupProperty(const nsACString& aProperty,
- EnabledState aEnabled)
+ EnabledState aEnabled,
+ nsCSSProperty* aAliasPropID /* outparam */)
{
MOZ_ASSERT(gPropertyTable, "no lookup table, needs addref");
+ if (aAliasPropID) {
+ *aAliasPropID = eCSSProperty_UNKNOWN;
+ }
+
if (nsLayoutUtils::CSSVariablesEnabled() &&
IsCustomPropertyName(aProperty)) {
return eCSSPropertyExtra_variable;
}
nsCSSProperty res = nsCSSProperty(gPropertyTable->Lookup(aProperty));
if (MOZ_LIKELY(res < eCSSProperty_COUNT)) {
if (res != eCSSProperty_UNKNOWN && !IsEnabled(res, aEnabled)) {
@@ -536,29 +541,41 @@ nsCSSProps::LookupProperty(const nsACStr
}
return res;
}
MOZ_ASSERT(eCSSAliasCount != 0,
"'res' must be an alias at this point so we better have some!");
// We intentionally don't support eEnabledInUASheets or eEnabledInChrome
// for aliases yet because it's unlikely there will be a need for it.
if (IsEnabled(res) || aEnabled == eIgnoreEnabledState) {
+ // Save the alias's propID. (Don't set outparam yet, though - not until
+ // we're sure we're succeeding.)
+ nsCSSProperty aliasPropID = res;
res = gAliases[res - eCSSProperty_COUNT];
MOZ_ASSERT(0 <= res && res < eCSSProperty_COUNT,
"aliases must not point to other aliases");
if (IsEnabled(res) || aEnabled == eIgnoreEnabledState) {
+ if (aAliasPropID) {
+ *aAliasPropID = aliasPropID;
+ }
return res;
}
}
return eCSSProperty_UNKNOWN;
}
nsCSSProperty
-nsCSSProps::LookupProperty(const nsAString& aProperty, EnabledState aEnabled)
+nsCSSProps::LookupProperty(const nsAString& aProperty,
+ EnabledState aEnabled,
+ nsCSSProperty* aAliasPropID /* outparam */)
{
+ if (aAliasPropID) {
+ *aAliasPropID = eCSSProperty_UNKNOWN;
+ }
+
if (nsLayoutUtils::CSSVariablesEnabled() &&
IsCustomPropertyName(aProperty)) {
return eCSSPropertyExtra_variable;
}
// This is faster than converting and calling
// LookupProperty(nsACString&). The table will do its own
// converting and avoid a PromiseFlatCString() call.
@@ -570,20 +587,26 @@ nsCSSProps::LookupProperty(const nsAStri
}
return res;
}
MOZ_ASSERT(eCSSAliasCount != 0,
"'res' must be an alias at this point so we better have some!");
// We intentionally don't support eEnabledInUASheets or eEnabledInChrome
// for aliases yet because it's unlikely there will be a need for it.
if (IsEnabled(res) || aEnabled == eIgnoreEnabledState) {
+ // Save the alias's propID. (Don't set outparam yet, though - not until
+ // we're sure we're succeeding.)
+ nsCSSProperty aliasPropID = res;
res = gAliases[res - eCSSProperty_COUNT];
MOZ_ASSERT(0 <= res && res < eCSSProperty_COUNT,
"aliases must not point to other aliases");
if (IsEnabled(res) || aEnabled == eIgnoreEnabledState) {
+ if (aAliasPropID) {
+ *aAliasPropID = aliasPropID;
+ }
return res;
}
}
return eCSSProperty_UNKNOWN;
}
nsCSSProperty
nsCSSProps::LookupPropertyByIDLName(const nsACString& aPropertyIDLName,
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -354,22 +354,34 @@ public:
// Special value to unconditionally enable a property. This implies all the
// bits above, but is strictly more than just their OR-ed union.
// This just skips any test so a property will be enabled even if it would
// have been disabled with all the bits above set.
eIgnoreEnabledState = 0xff
};
// Looks up the property with name aProperty and returns its corresponding
- // nsCSSProperty value. If aProperty is the name of a custom property,
- // then eCSSPropertyExtra_variable will be returned.
+ // nsCSSProperty value.
+ // * If aProperty is the name of a custom property, then
+ // eCSSPropertyExtra_variable will be returned.
+ // * If aProperty is the name of a property alias (e.g. a vendor-prefixed
+ // property name), then the target (unprefixed) property ID will be
+ // returned.
+ //
+ // If the outparam 'aAliasPropID' is non-null, this function will set its
+ // value to indicate whether aProperty is the name of an alias. Specifically:
+ // if aProperty _is_ the name of an alias, then *aAliasPropID will be set to
+ // the nsCSSProperty ID for the alias. Otherwise, *aAliasPropID will be set
+ // to eCSSProperty_UNKNOWN.
static nsCSSProperty LookupProperty(const nsAString& aProperty,
- EnabledState aEnabled);
+ EnabledState aEnabled,
+ nsCSSProperty* aAliasPropID = nullptr);
static nsCSSProperty LookupProperty(const nsACString& aProperty,
- EnabledState aEnabled);
+ EnabledState aEnabled,
+ nsCSSProperty* aAliasPropID = nullptr);
// As above, but looked up using a property's IDL name.
// eCSSPropertyExtra_variable won't be returned from these methods.
static nsCSSProperty LookupPropertyByIDLName(
const nsAString& aPropertyIDLName,
EnabledState aEnabled);
static nsCSSProperty LookupPropertyByIDLName(
const nsACString& aPropertyIDLName,
EnabledState aEnabled);