| Index: tool/input_sdk/private/js_number.dart
|
| diff --git a/tool/input_sdk/private/js_number.dart b/tool/input_sdk/private/js_number.dart
|
| index ced02db358b9ef666af8bdb1d48b3668134a56b8..65da0c81882d3fd3ade0e93a6e681dc72dedcdd8 100644
|
| --- a/tool/input_sdk/private/js_number.dart
|
| +++ b/tool/input_sdk/private/js_number.dart
|
| @@ -5,19 +5,14 @@
|
| part of dart._interceptors;
|
|
|
| /**
|
| - * The super interceptor class for [JSInt] and [JSDouble]. The compiler
|
| - * recognizes this class as an interceptor, and changes references to
|
| - * [:this:] to actually use the receiver of the method, which is
|
| - * generated as an extra argument added to each member.
|
| - *
|
| - * Note that none of the methods here delegate to a method defined on JSInt or
|
| - * JSDouble. This is exploited in [tryComputeConstantInterceptor].
|
| + * The implementation of Dart's int & double methods.
|
| + * These are made available as extension methods on `Number` in JS.
|
| */
|
| -class JSNumber extends Interceptor implements num {
|
| +@JsPeerInterface(name: 'Number')
|
| +class JSNumber extends Interceptor implements int, double {
|
| const JSNumber();
|
|
|
| int compareTo(num b) {
|
| - if (b is! num) throw new ArgumentError(b);
|
| if (this < b) {
|
| return -1;
|
| } else if (this > b) {
|
| @@ -51,15 +46,14 @@ class JSNumber extends Interceptor implements num {
|
|
|
| bool get isFinite => JS('bool', r'isFinite(#)', this);
|
|
|
| - num remainder(num b) {
|
| + JSNumber remainder(num b) {
|
| checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it.
|
| - if (b is! num) throw new ArgumentError(b);
|
| return JS('num', r'# % #', this, b);
|
| }
|
|
|
| - num abs() => JS('num', r'Math.abs(#)', this);
|
| + JSNumber abs() => JS('num', r'Math.abs(#)', this);
|
|
|
| - num get sign => this > 0 ? 1 : this < 0 ? -1 : this;
|
| + JSNumber get sign => this > 0 ? 1 : this < 0 ? -1 : this;
|
|
|
| static const int _MIN_INT32 = -0x80000000;
|
| static const int _MAX_INT32 = 0x7FFFFFFF;
|
| @@ -95,8 +89,6 @@ class JSNumber extends Interceptor implements num {
|
| double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble();
|
|
|
| num clamp(num lowerLimit, num upperLimit) {
|
| - if (lowerLimit is! num) throw new ArgumentError(lowerLimit);
|
| - if (upperLimit is! num) throw new ArgumentError(upperLimit);
|
| if (lowerLimit.compareTo(upperLimit) > 0) {
|
| throw new ArgumentError(lowerLimit);
|
| }
|
| @@ -105,9 +97,7 @@ class JSNumber extends Interceptor implements num {
|
| return this;
|
| }
|
|
|
| - // The return type is intentionally omitted to avoid type checker warnings
|
| - // from assigning JSNumber to double.
|
| - toDouble() => this;
|
| + double toDouble() => this;
|
|
|
| String toStringAsFixed(int fractionDigits) {
|
| checkInt(fractionDigits);
|
| @@ -186,33 +176,33 @@ class JSNumber extends Interceptor implements num {
|
|
|
| int get hashCode => JS('int', '# & 0x1FFFFFFF', this);
|
|
|
| - num operator -() => JS('num', r'-#', this);
|
| + JSNumber operator -() => JS('num', r'-#', this);
|
|
|
| - num operator +(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + JSNumber operator +(num other) {
|
| + checkNull(other);
|
| return JS('num', '# + #', this, other);
|
| }
|
|
|
| - num operator -(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + JSNumber operator -(num other) {
|
| + checkNull(other);
|
| return JS('num', '# - #', this, other);
|
| }
|
|
|
| double operator /(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return JS('double', '# / #', this, other);
|
| }
|
|
|
| - num operator *(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + JSNumber operator *(num other) {
|
| + checkNull(other);
|
| return JS('num', '# * #', this, other);
|
| }
|
|
|
| - num operator %(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + JSNumber operator %(num other) {
|
| + checkNull(other);
|
| // Euclidean Modulo.
|
| num result = JS('num', r'# % #', this, other);
|
| - if (result == 0) return 0; // Make sure we don't return -0.0.
|
| + if (result == 0) return (0 as JSNumber); // Make sure we don't return -0.0.
|
| if (result > 0) return result;
|
| if (JS('num', '#', other) < 0) {
|
| return result - JS('num', '#', other);
|
| @@ -224,7 +214,6 @@ class JSNumber extends Interceptor implements num {
|
| bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value);
|
|
|
| int operator ~/(num other) {
|
| - if (false) _tdivFast(other); // Ensure resolution.
|
| if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) {
|
| return JS('int', r'(# / #) | 0', this, other);
|
| } else {
|
| @@ -232,14 +221,8 @@ class JSNumber extends Interceptor implements num {
|
| }
|
| }
|
|
|
| - int _tdivFast(num other) {
|
| - return _isInt32(this)
|
| - ? JS('int', r'(# / #) | 0', this, other)
|
| - : (JS('num', r'# / #', this, other)).toInt();
|
| - }
|
| -
|
| int _tdivSlow(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return (JS('num', r'# / #', this, other)).toInt();
|
| }
|
|
|
| @@ -248,43 +231,35 @@ class JSNumber extends Interceptor implements num {
|
| // we define these methods on number for now but we need to decide
|
| // the grain at which we do the type checks.
|
|
|
| - num operator <<(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| - if (JS('num', '#', other) < 0) throw new ArgumentError(other);
|
| + int operator <<(num other) {
|
| + if (other < 0) throw new ArgumentError(other);
|
| return _shlPositive(other);
|
| }
|
|
|
| - num _shlPositive(num other) {
|
| + int _shlPositive(num other) {
|
| // JavaScript only looks at the last 5 bits of the shift-amount. Shifting
|
| // by 33 is hence equivalent to a shift by 1.
|
| return JS('bool', r'# > 31', other)
|
| ? 0
|
| - : JS('JSUInt32', r'(# << #) >>> 0', this, other);
|
| + : JS('int', r'(# << #) >>> 0', this, other);
|
| }
|
|
|
| - num operator >>(num other) {
|
| - if (false) _shrReceiverPositive(other);
|
| - if (other is !num) throw new ArgumentError(other);
|
| - if (JS('num', '#', other) < 0) throw new ArgumentError(other);
|
| + int operator >>(num other) {
|
| + if (other < 0) throw new ArgumentError(other);
|
| return _shrOtherPositive(other);
|
| }
|
|
|
| - num _shrOtherPositive(num other) {
|
| + int _shrOtherPositive(num other) {
|
| return JS('num', '#', this) > 0
|
| ? _shrBothPositive(other)
|
| // For negative numbers we just clamp the shift-by amount.
|
| // `this` could be negative but not have its 31st bit set.
|
| // The ">>" would then shift in 0s instead of 1s. Therefore
|
| // we cannot simply return 0xFFFFFFFF.
|
| - : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other);
|
| + : JS('int', r'(# >> #) >>> 0', this, other > 31 ? 31 : other);
|
| }
|
|
|
| - num _shrReceiverPositive(num other) {
|
| - if (JS('num', '#', other) < 0) throw new ArgumentError(other);
|
| - return _shrBothPositive(other);
|
| - }
|
| -
|
| - num _shrBothPositive(num other) {
|
| + int _shrBothPositive(num other) {
|
| return JS('bool', r'# > 31', other)
|
| // JavaScript only looks at the last 5 bits of the shift-amount. In JS
|
| // shifting by 33 is hence equivalent to a shift by 1. Shortcut the
|
| @@ -293,61 +268,48 @@ class JSNumber extends Interceptor implements num {
|
| // Given that `this` is positive we must not use '>>'. Otherwise a
|
| // number that has the 31st bit set would be treated as negative and
|
| // shift in ones.
|
| - : JS('JSUInt32', r'# >>> #', this, other);
|
| + : JS('int', r'# >>> #', this, other);
|
| }
|
|
|
| - num operator &(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| - return JS('JSUInt32', r'(# & #) >>> 0', this, other);
|
| + int operator &(num other) {
|
| + checkNull(other);
|
| + return JS('int', r'(# & #) >>> 0', this, other);
|
| }
|
|
|
| - num operator |(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| - return JS('JSUInt32', r'(# | #) >>> 0', this, other);
|
| + int operator |(num other) {
|
| + checkNull(other);
|
| + return JS('int', r'(# | #) >>> 0', this, other);
|
| }
|
|
|
| - num operator ^(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| - return JS('JSUInt32', r'(# ^ #) >>> 0', this, other);
|
| + int operator ^(num other) {
|
| + checkNull(other);
|
| + return JS('int', r'(# ^ #) >>> 0', this, other);
|
| }
|
|
|
| bool operator <(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return JS('bool', '# < #', this, other);
|
| }
|
|
|
| bool operator >(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return JS('bool', '# > #', this, other);
|
| }
|
|
|
| bool operator <=(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return JS('bool', '# <= #', this, other);
|
| }
|
|
|
| bool operator >=(num other) {
|
| - if (other is !num) throw new ArgumentError(other);
|
| + checkNull(other);
|
| return JS('bool', '# >= #', this, other);
|
| }
|
|
|
| - Type get runtimeType => num;
|
| -}
|
| -
|
| -/**
|
| - * The interceptor class for [int]s.
|
| - *
|
| - * This class implements double since in JavaScript all numbers are doubles, so
|
| - * while we want to treat `2.0` as an integer for some operations, its
|
| - * interceptor should answer `true` to `is double`.
|
| - */
|
| -// TODO(jmesserly): for dev_compiler all numbers will get `int` members at
|
| -// runtime for dynamic dispatch. We can fix by checking it at dispatch time.
|
| -// TODO(jmesserly): merge with JSNumber? That would simplify generated code,
|
| -// and dart_runtime's extension mechanism.
|
| -@JsPeerInterface(name: 'Number')
|
| -class JSInt extends JSNumber implements int, double {
|
| - const JSInt();
|
| + // int members.
|
| + // TODO(jmesserly): all numbers will have these in dynamic dispatch.
|
| + // We can fix by checking it at dispatch time but we'd need to structure them
|
| + // differently.
|
|
|
| bool get isEven => (this & 1) == 0;
|
|
|
| @@ -412,16 +374,5 @@ class JSInt extends JSNumber implements int, double {
|
| return i;
|
| }
|
|
|
| - Type get runtimeType => int;
|
| -
|
| - int operator ~() => JS('JSUInt32', r'(~#) >>> 0', this);
|
| + int operator ~() => JS('int', r'(~#) >>> 0', this);
|
| }
|
| -
|
| -class JSDouble extends JSNumber implements double {
|
| - const JSDouble();
|
| - Type get runtimeType => double;
|
| -}
|
| -
|
| -class JSPositiveInt extends JSInt {}
|
| -class JSUInt32 extends JSPositiveInt {}
|
| -class JSUInt31 extends JSUInt32 {}
|
|
|