summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorMartok <martok@martoks-place.de>2023-03-05 23:05:33 +0100
committerMartok <martok@martoks-place.de>2023-03-05 23:06:55 +0100
commit958b02c358d36112ba2fcc53514955ef88e190a2 (patch)
tree838b387aff3aa7daf5226bfa139d55d2c383cf83 /layout
parent5b9f0fd79654f640362959e02e097a171bebb1b0 (diff)
downloaduxp-958b02c358d36112ba2fcc53514955ef88e190a2.tar.gz
Issue #2143 - Implement CSS env() Environment Variables
Diffstat (limited to 'layout')
-rw-r--r--layout/style/nsCSSParser.cpp78
-rw-r--r--layout/style/nsCSSScanner.cpp6
2 files changed, 61 insertions, 23 deletions
diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
index 7bb18bc810..f9f198417f 100644
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -2638,6 +2638,25 @@ StopRecordingAndAppendTokens(nsString& aResult,
}
}
+static bool
+ResolveEnvironmentVariable(const nsAString& aName,
+ nsString& aValue,
+ nsCSSTokenSerializationType& aFirstToken,
+ nsCSSTokenSerializationType& aLastToken)
+{
+ // hard-code the few values of the Environment Variables spec
+ if (aName.EqualsLiteral("safe-area-inset-top") ||
+ aName.EqualsLiteral("safe-area-inset-bottom") ||
+ aName.EqualsLiteral("safe-area-inset-left") ||
+ aName.EqualsLiteral("safe-area-inset-right")) {
+ aValue.AppendLiteral(" 0px");
+ aFirstToken = eCSSTokenSerialization_Whitespace;
+ aLastToken = eCSSTokenSerialization_Dimension;
+ return true;
+ }
+ return false;
+}
+
bool
CSSParserImpl::ResolveValueWithVariableReferencesRec(
nsString& aResult,
@@ -2755,8 +2774,10 @@ CSSParserImpl::ResolveValueWithVariableReferencesRec(
}
case eCSSToken_Function:
- if (mToken.mIdent.LowerCaseEqualsLiteral("var")) {
- // Save the tokens before the "var(" to our resolved value.
+ if (mToken.mIdent.LowerCaseEqualsLiteral("env") ||
+ mToken.mIdent.LowerCaseEqualsLiteral("var")) {
+ bool functionIsVariable = mToken.mIdent.LowerCaseEqualsLiteral("var");
+ // Save the tokens before the "env(" to our resolved value.
nsString recording;
mScanner->StopRecording(recording);
recording.Truncate(lengthBeforeVar);
@@ -2766,30 +2787,43 @@ CSSParserImpl::ResolveValueWithVariableReferencesRec(
recLastToken = eCSSTokenSerialization_Nothing;
if (!GetToken(true) ||
- mToken.mType != eCSSToken_Ident ||
- !nsCSSProps::IsCustomPropertyName(mToken.mIdent)) {
- // "var(" must be followed by an identifier, and it must be a
- // custom property name.
+ mToken.mType != eCSSToken_Ident) {
+ // function must be followed by an identifier
return false;
}
- // Turn the custom property name into a variable name by removing the
- // '--' prefix.
- MOZ_ASSERT(Substring(mToken.mIdent, 0,
- CSS_CUSTOM_NAME_PREFIX_LENGTH).
- 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.
+ // Expand the function call into variableValue
nsString variableValue;
- nsCSSTokenSerializationType varFirstToken, varLastToken;
- bool valid = aVariables->Get(variableName, variableValue,
- varFirstToken, varLastToken) &&
- !variableValue.IsEmpty();
+ nsCSSTokenSerializationType varFirstToken = eCSSTokenSerialization_Nothing;
+ nsCSSTokenSerializationType varLastToken = eCSSTokenSerialization_Nothing;
+ bool valid = false;
+
+ if (functionIsVariable) {
+ if (!nsCSSProps::IsCustomPropertyName(mToken.mIdent)) {
+ // "var(" identifier must be a custom property name.
+ return false;
+ }
+
+ // Turn the custom property name into a variable name by removing the
+ // '--' prefix.
+ MOZ_ASSERT(Substring(mToken.mIdent, 0,
+ CSS_CUSTOM_NAME_PREFIX_LENGTH).
+ 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.
+ valid = aVariables->Get(variableName, variableValue,
+ varFirstToken, varLastToken) &&
+ !variableValue.IsEmpty();
+ } else {
+ valid = ResolveEnvironmentVariable(mToken.mIdent, variableValue,
+ varFirstToken,varLastToken) &&
+ !variableValue.IsEmpty();
+ }
if (!GetToken(true) ||
mToken.IsSymbol(')')) {
diff --git a/layout/style/nsCSSScanner.cpp b/layout/style/nsCSSScanner.cpp
index b1524a3bb2..8010d86b67 100644
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -752,7 +752,11 @@ nsCSSScanner::ScanIdent(nsCSSToken& aToken)
aToken.mType = eCSSToken_Function;
if (aToken.mIdent.LowerCaseEqualsLiteral("url")) {
NextURL(aToken);
- } else if (aToken.mIdent.LowerCaseEqualsLiteral("var")) {
+ } else if (aToken.mIdent.LowerCaseEqualsLiteral("var") ||
+ aToken.mIdent.LowerCaseEqualsLiteral("env")) {
+ // env() queries are technically not variables, but share all the
+ // same handling. For the purposes of resolving the token stream later,
+ // pretend they are.
mSeenVariableReference = true;
}
return true;