Stop simplifying calculations in supports (#1653)

Fixes #1652.

Also releases 1.49.10
This commit is contained in:
Jennifer Thakar 2022-03-30 15:14:46 -07:00 committed by GitHub
parent 55157a576e
commit 6652001f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 14 deletions

View File

@ -19,6 +19,8 @@
could be emitted as a hex color rather than a format with higher browser
compatibility.
* Calculations are no longer simplified within supports declarations
## 1.49.9
### Embedded Sass

View File

@ -35,6 +35,13 @@ class SassCalculation extends Value {
@internal
bool get isSpecialNumber => true;
/// Creates a new calculation with the given [name] and [arguments]
/// that will not be simplified.
@internal
static Value unsimplified(String name, Iterable<Object> arguments) {
return SassCalculation._(name, List.unmodifiable(arguments));
}
/// Creates a `calc()` calculation with the given [argument].
///
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
@ -162,17 +169,22 @@ class SassCalculation extends Value {
/// a [CalculationInterpolation].
static Object operate(
CalculationOperator operator, Object left, Object right) =>
operateInternal(operator, left, right, inMinMax: false);
operateInternal(operator, left, right, inMinMax: false, simplify: true);
/// Like [operate], but with the internal-only [inMinMax] parameter.
///
/// If [inMinMax] is `true`, this allows unitless numbers to be added and
/// subtracted with numbers with units, for backwards-compatibility with the
/// old global `min()` and `max()` functions.
///
/// If [simplify] is `false`, no simplification will be done.
@internal
static Object operateInternal(
CalculationOperator operator, Object left, Object right,
{required bool inMinMax}) {
{required bool inMinMax, required bool simplify}) {
if (!simplify) {
return CalculationOperation._(operator, left, right);
}
left = _simplify(left);
right = _simplify(right);

View File

@ -219,6 +219,11 @@ class _EvaluateVisitor
/// Whether we're currently building the output of a `@keyframes` rule.
var _inKeyframes = false;
/// Whether we're currently evaluating a [SupportsDeclaration].
///
/// When this is true, calculations will not be simplified.
var _inSupportsDeclaration = false;
/// The canonical URLs of all stylesheets loaded during compilation.
final _loadedUrls = <Uri>{};
@ -1949,9 +1954,13 @@ class _EvaluateVisitor
} else if (condition is SupportsInterpolation) {
return await _evaluateToCss(condition.expression, quote: false);
} else if (condition is SupportsDeclaration) {
return "(${await _evaluateToCss(condition.name)}:"
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = true;
var result = "(${await _evaluateToCss(condition.name)}:"
"${condition.isCustomProperty ? '' : ' '}"
"${await _evaluateToCss(condition.value)})";
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
} else if (condition is SupportsFunction) {
return "${await _performInterpolation(condition.name)}("
"${await _performInterpolation(condition.arguments)})";
@ -2227,6 +2236,9 @@ class _EvaluateVisitor
await _visitCalculationValue(argument,
inMinMax: node.name == 'min' || node.name == 'max')
];
if (_inSupportsDeclaration) {
return SassCalculation.unsimplified(node.name, arguments);
}
try {
switch (node.name) {
@ -2317,7 +2329,8 @@ class _EvaluateVisitor
_binaryOperatorToCalculationOperator(node.operator),
await _visitCalculationValue(node.left, inMinMax: inMinMax),
await _visitCalculationValue(node.right, inMinMax: inMinMax),
inMinMax: inMinMax));
inMinMax: inMinMax,
simplify: !_inSupportsDeclaration));
} else {
assert(node is NumberExpression ||
node is CalculationExpression ||
@ -2823,7 +2836,9 @@ class _EvaluateVisitor
Future<SassString> visitStringExpression(StringExpression node) async {
// Don't use [performInterpolation] here because we need to get the raw text
// from strings, rather than the semantic value.
return SassString(
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = false;
var result = SassString(
(await mapAsync(node.text.contents, (value) async {
if (value is String) return value;
var expression = value as Expression;
@ -2834,6 +2849,8 @@ class _EvaluateVisitor
}))
.join(),
quotes: node.hasQuotes);
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
}
// ## Plain CSS
@ -3088,7 +3105,9 @@ class _EvaluateVisitor
/// values passed into the interpolation.
Future<String> _performInterpolation(Interpolation interpolation,
{bool warnForColor = false}) async {
return (await mapAsync(interpolation.contents, (value) async {
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = false;
var result = (await mapAsync(interpolation.contents, (value) async {
if (value is String) return value;
var expression = value as Expression;
var result = await expression.accept(this);
@ -3115,6 +3134,8 @@ class _EvaluateVisitor
return _serialize(result, expression, quote: false);
}))
.join();
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
}
/// Evaluates [expression] and calls `toCssString()` and wraps a

View File

@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: f11bdd289c888e0e0737bc96e63283bc8a332d9a
// Checksum: 45277707f5ab21408f3abb8f249ed7115e0a3c0f
//
// ignore_for_file: unused_import
@ -227,6 +227,11 @@ class _EvaluateVisitor
/// Whether we're currently building the output of a `@keyframes` rule.
var _inKeyframes = false;
/// Whether we're currently evaluating a [SupportsDeclaration].
///
/// When this is true, calculations will not be simplified.
var _inSupportsDeclaration = false;
/// The canonical URLs of all stylesheets loaded during compilation.
final _loadedUrls = <Uri>{};
@ -1942,9 +1947,13 @@ class _EvaluateVisitor
} else if (condition is SupportsInterpolation) {
return _evaluateToCss(condition.expression, quote: false);
} else if (condition is SupportsDeclaration) {
return "(${_evaluateToCss(condition.name)}:"
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = true;
var result = "(${_evaluateToCss(condition.name)}:"
"${condition.isCustomProperty ? '' : ' '}"
"${_evaluateToCss(condition.value)})";
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
} else if (condition is SupportsFunction) {
return "${_performInterpolation(condition.name)}("
"${_performInterpolation(condition.arguments)})";
@ -2216,6 +2225,9 @@ class _EvaluateVisitor
_visitCalculationValue(argument,
inMinMax: node.name == 'min' || node.name == 'max')
];
if (_inSupportsDeclaration) {
return SassCalculation.unsimplified(node.name, arguments);
}
try {
switch (node.name) {
@ -2305,7 +2317,8 @@ class _EvaluateVisitor
_binaryOperatorToCalculationOperator(node.operator),
_visitCalculationValue(node.left, inMinMax: inMinMax),
_visitCalculationValue(node.right, inMinMax: inMinMax),
inMinMax: inMinMax));
inMinMax: inMinMax,
simplify: !_inSupportsDeclaration));
} else {
assert(node is NumberExpression ||
node is CalculationExpression ||
@ -2804,7 +2817,9 @@ class _EvaluateVisitor
SassString visitStringExpression(StringExpression node) {
// Don't use [performInterpolation] here because we need to get the raw text
// from strings, rather than the semantic value.
return SassString(
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = false;
var result = SassString(
node.text.contents.map((value) {
if (value is String) return value;
var expression = value as Expression;
@ -2814,6 +2829,8 @@ class _EvaluateVisitor
: _serialize(result, expression, quote: false);
}).join(),
quotes: node.hasQuotes);
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
}
// ## Plain CSS
@ -3064,7 +3081,9 @@ class _EvaluateVisitor
/// values passed into the interpolation.
String _performInterpolation(Interpolation interpolation,
{bool warnForColor = false}) {
return interpolation.contents.map((value) {
var oldInSupportsDeclaration = _inSupportsDeclaration;
_inSupportsDeclaration = false;
var result = interpolation.contents.map((value) {
if (value is String) return value;
var expression = value as Expression;
var result = expression.accept(this);
@ -3090,6 +3109,8 @@ class _EvaluateVisitor
return _serialize(result, expression, quote: false);
}).join();
_inSupportsDeclaration = oldInSupportsDeclaration;
return result;
}
/// Evaluates [expression] and calls `toCssString()` and wraps a

View File

@ -1,3 +1,7 @@
## 1.0.0-beta.39
* No user-visible changes.
## 1.0.0-beta.38
* No user-visible changes.

View File

@ -2,7 +2,7 @@ name: sass_api
# Note: Every time we add a new Sass AST node, we need to bump the *major*
# version because it's a breaking change for anyone who's implementing the
# visitor interface(s).
version: 1.0.0-beta.38
version: 1.0.0-beta.39
description: Additional APIs for Dart Sass.
homepage: https://github.com/sass/dart-sass
@ -10,7 +10,7 @@ environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
sass: 1.49.9
sass: 1.49.10
dependency_overrides:
sass: {path: ../..}

View File

@ -1,5 +1,5 @@
name: sass
version: 1.49.10-dev
version: 1.49.10
description: A Sass implementation in Dart.
homepage: https://github.com/sass/dart-sass