diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp index 7491c73644..4a5d2c39b5 100644 --- a/layout/style/CSSStyleSheet.cpp +++ b/layout/style/CSSStyleSheet.cpp @@ -310,7 +310,8 @@ nsMediaExpression::Matches(nsPresContext *aPresContext, case nsMediaFeature::eLength: { NS_ASSERTION(actual.IsLengthUnit(), "bad actual value"); - NS_ASSERTION(required.IsLengthUnit(), "bad required value"); + NS_ASSERTION(required.IsLengthUnit() || required.IsCalcUnit(), + "bad required value"); nscoord actualCoord = nsRuleNode::CalcLengthWithInitialFont( aPresContext, actual); nscoord requiredCoord = nsRuleNode::CalcLengthWithInitialFont( @@ -649,7 +650,8 @@ nsMediaQuery::AppendToString(nsAString& aString) const } switch (feature->mValueType) { case nsMediaFeature::eLength: - NS_ASSERTION(expr.mValue.IsLengthUnit(), "bad unit"); + NS_ASSERTION(expr.mValue.IsLengthUnit() || expr.mValue.IsCalcUnit(), + "bad unit"); // Use 'width' as a property that takes length values // written in the normal way. expr.mValue.AppendToString(eCSSProperty_width, aString, diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 29e2bc27ca..0ed0773844 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -3998,7 +3998,7 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) bool rv = false; switch (feature->mValueType) { case nsMediaFeature::eLength: - rv = ParseSingleTokenNonNegativeVariant(expr->mValue, VARIANT_LENGTH, + rv = ParseSingleTokenNonNegativeVariant(expr->mValue, VARIANT_LCALC, nullptr); break; case nsMediaFeature::eInteger: diff --git a/layout/style/test/test_media_queries.html b/layout/style/test/test_media_queries.html index 90b55a2ac5..c2176f9283 100644 --- a/layout/style/test/test_media_queries.html +++ b/layout/style/test/test_media_queries.html @@ -237,6 +237,7 @@ function run() { expression_should_be_parseable(feature + ": 0"); expression_should_be_parseable(feature + ": 0px"); expression_should_be_parseable(feature + ": 0em"); + expression_should_be_parseable(feature + ": calc(0px + 0em)"); expression_should_be_parseable(feature + ": -0"); expression_should_be_parseable("min-" + feature + ": -0"); expression_should_be_parseable("max-" + feature + ": -0"); @@ -244,6 +245,7 @@ function run() { expression_should_be_parseable(feature + ": 1px"); expression_should_be_parseable(feature + ": 0.001mm"); expression_should_be_parseable(feature + ": 100000px"); + expression_should_not_be_parseable(feature + ": calc(1px + 1%)"); expression_should_not_be_parseable(feature + ": -1px"); expression_should_not_be_parseable("min-" + feature + ": -1px"); expression_should_not_be_parseable("max-" + feature + ": -1px"); @@ -263,8 +265,9 @@ function run() { var content_div = document.getElementById("content"); content_div.style.font = "initial"; - var em_size = - getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1]; + var em_size = parseFloat( + getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1] + ); // in this test, assume the common underlying implementation is correct var width_val = 117; // pick two not-too-round numbers @@ -282,7 +285,11 @@ function run() { for (feature in features) { var value = features[feature]; should_apply("all and (" + feature + ": " + value + "px)"); + should_apply("all and (" + feature + ": calc(" + + (value - em_size) + "px + 1em))"); should_not_apply("all and (" + feature + ": " + (value + 1) + "px)"); + should_not_apply("all and (" + feature + ": calc(" + + (value - em_size + 1) + "px + 1em))"); should_not_apply("all and (" + feature + ": " + (value - 1) + "px)"); should_apply("all and (min-" + feature + ": " + value + "px)"); should_not_apply("all and (min-" + feature + ": " + (value + 1) + "px)");