Index: pkg/compiler/lib/src/js_backend/constant_system_javascript.dart |
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart |
index 7f86482fd595d79f5dd2fbe2706e5801d8b29bb7..08174df252d834880d872d183b866b6d0a548a9e 100644 |
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart |
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart |
@@ -165,12 +165,50 @@ class JavaScriptIdentityOperation implements BinaryOperation { |
apply(left, right) => identical(left, right); |
} |
+class JavaScriptRoundOperation implements UnaryOperation { |
+ const JavaScriptRoundOperation(); |
+ String get name => DART_CONSTANT_SYSTEM.round.name; |
+ ConstantValue fold(ConstantValue constant) { |
+ // Be careful to round() only values that do not throw on either the host or |
+ // target platform. |
+ ConstantValue tryToRound(num value) { |
+ // Due to differences between browsers, only 'round' easy cases. Avoid |
+ // cases where nudging the value up or down changes the answer. |
+ // 13 digits is safely within the ~15 digit precision of doubles. |
+ const severalULP = 0.0000000000001; |
+ // Use 'roundToDouble()' to avoid exceptions on rounding the nudged value. |
+ double rounded = value.roundToDouble(); |
+ double rounded1 = (value * (1.0 + severalULP)).roundToDouble(); |
+ double rounded2 = (value * (1.0 - severalULP)).roundToDouble(); |
+ if (rounded != rounded1 || rounded != rounded2) return null; |
+ return JAVA_SCRIPT_CONSTANT_SYSTEM |
+ .convertToJavaScriptConstant(new IntConstantValue(value.round())); |
+ } |
+ |
+ if (constant.isInt) { |
+ IntConstantValue intConstant = constant; |
+ int value = intConstant.primitiveValue; |
+ if (value >= -double.MAX_FINITE && value <= double.MAX_FINITE) { |
+ return tryToRound(value); |
+ } |
+ } |
+ if (constant.isDouble) { |
+ DoubleConstantValue doubleConstant = constant; |
+ double value = doubleConstant.primitiveValue; |
+ // NaN and infinities will throw. |
+ if (value.isNaN) return null; |
+ if (value.isInfinite) return null; |
+ return tryToRound(value); |
+ } |
+ return null; |
+ } |
+} |
+ |
/** |
* Constant system following the semantics for Dart code that has been |
* compiled to JavaScript. |
*/ |
class JavaScriptConstantSystem extends ConstantSystem { |
- final int BITS31 = 0x8FFFFFFF; |
final int BITS32 = 0xFFFFFFFF; |
final add = const JavaScriptAddOperation(); |
@@ -203,6 +241,7 @@ class JavaScriptConstantSystem extends ConstantSystem { |
final truncatingDivide = const JavaScriptBinaryArithmeticOperation( |
const TruncatingDivideOperation()); |
final codeUnitAt = const CodeUnitAtRuntimeOperation(); |
+ final round = const JavaScriptRoundOperation(); |
const JavaScriptConstantSystem(); |