Remove some unnecessary dynamic invocations in the platform libraries.

Change-Id: Ia72033e37c4d8292eabd95aeff97e4cb29e81823
Reviewed-on: https://dart-review.googlesource.com/c/82204
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Lasse R.H. Nielsen
2018-11-02 11:32:03 +00:00
committed by commit-bot@chromium.org
parent 6d9dc93d0e
commit 5226b5c307
19 changed files with 175 additions and 191 deletions
@@ -344,10 +344,12 @@ class DateTime {
int get weekday => Primitives.getWeekday(this);
@patch
bool operator ==(Object other) =>
other is DateTime &&
_value == other.millisecondsSinceEpoch &&
isUtc == other.isUtc;
bool operator ==(dynamic other) {
Object promotableOther = other;
return promotableOther is DateTime &&
_value == promotableOther.millisecondsSinceEpoch &&
isUtc == promotableOther.isUtc;
}
@patch
bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
+6 -4
View File
@@ -73,10 +73,12 @@ class DateTime {
}
@patch
bool operator ==(Object other) =>
other is DateTime &&
_value == other.microsecondsSinceEpoch &&
isUtc == other.isUtc;
bool operator ==(dynamic other) {
Object promotableOther = other;
return promotableOther is DateTime &&
_value == promotableOther.microsecondsSinceEpoch &&
isUtc == promotableOther.isUtc;
}
@patch
bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
@@ -377,10 +377,12 @@ class DateTime {
int get weekday => Primitives.getWeekday(this);
@patch
bool operator ==(Object other) =>
other is DateTime &&
_value == other.millisecondsSinceEpoch &&
isUtc == other.isUtc;
bool operator ==(dynamic other) {
Object promotableOther = other;
return promotableOther is DateTime &&
_value == promotableOther.millisecondsSinceEpoch &&
isUtc == promotableOther.isUtc;
}
@patch
bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
+4
View File
@@ -7,6 +7,10 @@ part of dart.async;
_invokeErrorHandler(
Function errorHandler, Object error, StackTrace stackTrace) {
if (errorHandler is ZoneBinaryCallback<dynamic, Null, Null>) {
// Dynamic invocation because we don't know the actual type of the
// first argument or the error object, but we should successfully call
// the handler if they match up.
// TODO(lrn): Should we? Why not the same below for the unary case?
return (errorHandler as dynamic)(error, stackTrace);
} else {
ZoneUnaryCallback unaryErrorHandler = errorHandler;
@@ -57,11 +57,7 @@ class _BroadcastSubscription<T> extends _ControllerSubscription<T> {
}
abstract class _BroadcastStreamController<T>
implements
StreamController<T>,
_StreamControllerLifecycle<T>,
_EventSink<T>,
_EventDispatch<T> {
implements _StreamControllerBase<T> {
static const int _STATE_INITIAL = 0;
static const int _STATE_EVENT_ID = 1;
static const int _STATE_FIRING = 2;
+9 -5
View File
@@ -312,10 +312,14 @@ abstract class Future<T> {
factory Future.delayed(Duration duration, [FutureOr<T> computation()]) {
_Future<T> result = new _Future<T>();
new Timer(duration, () {
try {
result._complete(computation?.call());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
if (computation == null) {
result._complete(null);
} else {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
}
});
return result;
@@ -521,7 +525,7 @@ abstract class Future<T> {
*/
static Future doWhile(FutureOr<bool> action()) {
_Future doneSignal = new _Future();
var nextIteration;
void Function(bool) nextIteration;
// Bind this callback explicitly so that each iteration isn't bound in the
// context of all the previous iterations' callbacks.
// This avoids, e.g., deeply nested stack traces from the stack trace
+7 -10
View File
@@ -426,15 +426,14 @@ abstract class Stream<T> {
* The returned stream is a broadcast stream if this stream is.
*/
Stream<E> asyncMap<E>(FutureOr<E> convert(T event)) {
StreamController<E> controller;
_StreamControllerBase<E> controller;
StreamSubscription<T> subscription;
void onListen() {
final add = controller.add;
assert(controller is _StreamController ||
assert(controller is _StreamController<E> ||
controller is _BroadcastStreamController);
final _EventSink<E> eventSink = controller as Object;
final addError = eventSink._addError;
final addError = controller._addError;
subscription = this.listen((T event) {
FutureOr<E> newValue;
try {
@@ -495,12 +494,11 @@ abstract class Stream<T> {
* The returned stream is a broadcast stream if this stream is.
*/
Stream<E> asyncExpand<E>(Stream<E> convert(T event)) {
StreamController<E> controller;
_StreamControllerBase<E> controller;
StreamSubscription<T> subscription;
void onListen() {
assert(controller is _StreamController ||
controller is _BroadcastStreamController);
final _EventSink<E> eventSink = controller as Object;
subscription = this.listen((T event) {
Stream<E> newStream;
try {
@@ -514,7 +512,7 @@ abstract class Stream<T> {
controller.addStream(newStream).whenComplete(subscription.resume);
}
},
onError: eventSink._addError, // Avoid Zone error replacement.
onError: controller._addError, // Avoid Zone error replacement.
onDone: controller.close);
}
@@ -1474,7 +1472,7 @@ abstract class Stream<T> {
* and the subscriptions' timers can be paused individually.
*/
Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) {
StreamController<T> controller;
_StreamControllerBase<T> controller;
// The following variables are set on listen.
StreamSubscription<T> subscription;
Timer timer;
@@ -1491,8 +1489,7 @@ abstract class Stream<T> {
timer.cancel();
assert(controller is _StreamController ||
controller is _BroadcastStreamController);
dynamic eventSink = controller;
eventSink._addError(error, stackTrace); // Avoid Zone error replacement.
controller._addError(error, stackTrace); // Avoid Zone error replacement.
timer = zone.createTimer(timeLimit, timeout);
}
+9 -6
View File
@@ -381,17 +381,20 @@ abstract class _StreamControllerLifecycle<T> {
Future _recordCancel(StreamSubscription<T> subscription) => null;
}
// Base type for implementations of stream controllers.
abstract class _StreamControllerBase<T>
implements
StreamController<T>,
_StreamControllerLifecycle<T>,
_EventSink<T>,
_EventDispatch<T> {}
/**
* Default implementation of [StreamController].
*
* Controls a stream that only supports a single controller.
*/
abstract class _StreamController<T>
implements
StreamController<T>,
_StreamControllerLifecycle<T>,
_EventSink<T>,
_EventDispatch<T> {
abstract class _StreamController<T> implements _StreamControllerBase<T> {
// The states are bit-flags. More than one can be set at a time.
//
// The "subscription state" goes through the states:
+4 -4
View File
@@ -238,7 +238,7 @@ abstract class IterableBase<E> extends Iterable<E> {
}
return "$leftDelimiter...$rightDelimiter";
}
List parts = [];
List<String> parts = <String>[];
_toStringVisiting.add(iterable);
try {
_iterablePartsToStrings(iterable, parts);
@@ -296,7 +296,7 @@ bool _isToStringVisiting(Object o) {
/**
* Convert elements of [iterable] to strings and store them in [parts].
*/
void _iterablePartsToStrings(Iterable iterable, List parts) {
void _iterablePartsToStrings(Iterable iterable, List<String> parts) {
/*
* This is the complicated part of [iterableToShortString].
* It is extracted as a separate function to avoid having too much code
@@ -337,8 +337,8 @@ void _iterablePartsToStrings(Iterable iterable, List parts) {
// Find last two elements. One or more of them may already be in the
// parts array. Include their length in `length`.
var penultimate = null;
var ultimate = null;
Object penultimate = null;
Object ultimate = null;
if (!it.moveNext()) {
if (count <= headCount + tailCount) return;
ultimateString = parts.removeLast();
+4 -3
View File
@@ -13,9 +13,10 @@ abstract class Encoding extends Codec<String, List<int>> {
Future<String> decodeStream(Stream<List<int>> byteStream) {
return byteStream
.transform(decoder)
.fold(StringBuffer(), (buffer, string) => buffer..write(string))
.then((buffer) => buffer.toString());
.transform<String>(decoder)
.fold(StringBuffer(),
(StringBuffer buffer, String string) => buffer..write(string))
.then((StringBuffer buffer) => buffer.toString());
}
/// Name of the encoding.
+1 -1
View File
@@ -404,7 +404,7 @@ class DateTime implements Comparable<DateTime> {
* See [isAtSameMomentAs] for a comparison that compares moments in time
* independently of their zones.
*/
external bool operator ==(other);
external bool operator ==(dynamic other);
/**
* Returns true if [this] occurs before [other].
+16 -16
View File
@@ -23,32 +23,31 @@ part of dart.core;
*
* To create a new Duration object, use this class's single constructor
* giving the appropriate arguments:
*
* Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2);
*
* ```dart
* Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2);
* ```
* The [Duration] is the sum of all individual parts.
* This means that individual parts can be larger than the next-bigger unit.
* For example, [inMinutes] can be greater than 59.
*
* assert(fastestMarathon.inMinutes == 123);
*
* ```dart
* assert(fastestMarathon.inMinutes == 123);
* ```
* All individual parts are allowed to be negative.
*
* Use one of the properties, such as [inDays],
* to retrieve the integer value of the Duration in the specified time unit.
* Note that the returned value is rounded down.
* For example,
*
* Duration aLongWeekend = new Duration(hours:88);
* assert(aLongWeekend.inDays == 3);
*
* ```dart
* Duration aLongWeekend = new Duration(hours:88);
* assert(aLongWeekend.inDays == 3);
* ```
* This class provides a collection of arithmetic
* and comparison operators,
* plus a set of constants useful for converting time units.
*
* See [DateTime] to represent a point in time.
* See [Stopwatch] to measure time-spans.
*
*/
class Duration implements Comparable<Duration> {
static const int microsecondsPerMillisecond = 1000;
@@ -212,17 +211,18 @@ class Duration implements Comparable<Duration> {
int get inMicroseconds => _duration;
/**
* Returns `true` if this Duration is the same object as [other].
* Returns `true` if this [Duration] is the same object as [other].
*/
bool operator ==(other) {
if (other is! Duration) return false;
return _duration == other._duration;
bool operator ==(dynamic other) {
Object promotableOther = other;
return promotableOther is Duration &&
_duration == promotableOther.inMicroseconds;
}
int get hashCode => _duration.hashCode;
/**
* Compares this Duration to [other], returning zero if the values are equal.
* Compares this [Duration] to [other], returning zero if the values are equal.
*
* Returns a negative integer if this `Duration` is shorter than
* [other], or a positive integer if it is longer.
+6 -5
View File
@@ -265,7 +265,7 @@ class RangeError extends ArgumentError {
* The [length] is the length of [indexable] at the time of the error.
* If `length` is omitted, it defaults to `indexable.length`.
*/
factory RangeError.index(int index, indexable,
factory RangeError.index(int index, dynamic indexable,
[String name, String message, int length]) = IndexError;
/**
@@ -292,9 +292,9 @@ class RangeError extends ArgumentError {
* If [length] is provided, it is used as the length of the indexable object,
* otherwise the length is found as `indexable.length`.
*/
static void checkValidIndex(int index, var indexable,
static void checkValidIndex(int index, dynamic indexable,
[String name, int length, String message]) {
if (length == null) length = indexable.length;
length ??= indexable.length;
// Comparing with `0` as receiver produces better dart2js type inference.
if (0 > index || index >= length) {
if (name == null) name = "index";
@@ -390,10 +390,10 @@ class IndexError extends ArgumentError implements RangeError {
*
* The message is used as part of the string representation of the error.
*/
IndexError(int invalidValue, indexable,
IndexError(int invalidValue, dynamic indexable,
[String name, String message, int length])
: this.indexable = indexable,
this.length = (length != null) ? length : indexable.length,
this.length = length ?? indexable.length,
super.value(invalidValue, name,
(message != null) ? message : "Index out of range");
@@ -404,6 +404,7 @@ class IndexError extends ArgumentError implements RangeError {
String get _errorName => "RangeError";
String get _errorExplanation {
assert(_hasValue);
int invalidValue = this.invalidValue;
if (invalidValue < 0) {
return ": index must not be negative";
}
+70 -67
View File
@@ -98,78 +98,81 @@ class FormatException implements Exception {
report = "$report: $message";
}
int offset = this.offset;
if (source is! String) {
Object objectSource = this.source;
if (objectSource is String) {
String source = objectSource;
if (offset != null && (offset < 0 || offset > source.length)) {
offset = null;
}
// Source is string and offset is null or valid.
if (offset == null) {
if (source.length > 78) {
source = source.substring(0, 75) + "...";
}
return "$report\n$source";
}
int lineNum = 1;
int lineStart = 0;
bool previousCharWasCR = false;
for (int i = 0; i < offset; i++) {
int char = source.codeUnitAt(i);
if (char == 0x0a) {
if (lineStart != i || !previousCharWasCR) {
lineNum++;
}
lineStart = i + 1;
previousCharWasCR = false;
} else if (char == 0x0d) {
lineNum++;
lineStart = i + 1;
previousCharWasCR = true;
}
}
if (lineNum > 1) {
report += " (at line $lineNum, character ${offset - lineStart + 1})\n";
} else {
report += " (at character ${offset + 1})\n";
}
int lineEnd = source.length;
for (int i = offset; i < source.length; i++) {
int char = source.codeUnitAt(i);
if (char == 0x0a || char == 0x0d) {
lineEnd = i;
break;
}
}
int length = lineEnd - lineStart;
int start = lineStart;
int end = lineEnd;
String prefix = "";
String postfix = "";
if (length > 78) {
// Can't show entire line. Try to anchor at the nearest end, if
// one is within reach.
int index = offset - lineStart;
if (index < 75) {
end = start + 75;
postfix = "...";
} else if (end - offset < 75) {
start = end - 75;
prefix = "...";
} else {
// Neither end is near, just pick an area around the offset.
start = offset - 36;
end = offset + 36;
prefix = postfix = "...";
}
}
String slice = source.substring(start, end);
int markOffset = offset - start + prefix.length;
return "$report$prefix$slice$postfix\n${" " * markOffset}^\n";
} else {
// The source is not a string.
if (offset != null) {
report += " (at offset $offset)";
}
return report;
}
if (offset != null && (offset < 0 || offset > source.length)) {
offset = null;
}
// Source is string and offset is null or valid.
if (offset == null) {
String source = this.source;
if (source.length > 78) {
source = source.substring(0, 75) + "...";
}
return "$report\n$source";
}
int lineNum = 1;
int lineStart = 0;
bool previousCharWasCR = false;
for (int i = 0; i < offset; i++) {
int char = source.codeUnitAt(i);
if (char == 0x0a) {
if (lineStart != i || !previousCharWasCR) {
lineNum++;
}
lineStart = i + 1;
previousCharWasCR = false;
} else if (char == 0x0d) {
lineNum++;
lineStart = i + 1;
previousCharWasCR = true;
}
}
if (lineNum > 1) {
report += " (at line $lineNum, character ${offset - lineStart + 1})\n";
} else {
report += " (at character ${offset + 1})\n";
}
int lineEnd = source.length;
for (int i = offset; i < source.length; i++) {
int char = source.codeUnitAt(i);
if (char == 0x0a || char == 0x0d) {
lineEnd = i;
break;
}
}
int length = lineEnd - lineStart;
int start = lineStart;
int end = lineEnd;
String prefix = "";
String postfix = "";
if (length > 78) {
// Can't show entire line. Try to anchor at the nearest end, if
// one is within reach.
int index = offset - lineStart;
if (index < 75) {
end = start + 75;
postfix = "...";
} else if (end - offset < 75) {
start = end - 75;
prefix = "...";
} else {
// Neither end is near, just pick an area around the offset.
start = offset - 36;
end = offset + 36;
prefix = postfix = "...";
}
}
String slice = source.substring(start, end);
int markOffset = offset - start + prefix.length;
return "$report$prefix$slice$postfix\n${" " * markOffset}^\n";
}
}
+6 -5
View File
@@ -2114,7 +2114,7 @@ class _Uri implements Uri {
if (path != null && pathSegments != null) {
throw new ArgumentError('Both path and pathSegments specified');
}
var result;
String result;
if (path != null) {
result = _normalizeOrSubstring(path, start, end, _pathCharOrSlashTable,
escapeDelimiters: true);
@@ -2739,10 +2739,11 @@ class _Uri implements Uri {
return _hashCodeCache ??= toString().hashCode;
}
static List _createList() => [];
static List<String> _createList() => <String>[];
static Map _splitQueryStringAll(String query, {Encoding encoding: utf8}) {
Map result = {};
static Map<String, List<String>> _splitQueryStringAll(String query,
{Encoding encoding: utf8}) {
var result = <String, List<String>>{};
int i = 0;
int start = 0;
int equalsIndex = -1;
@@ -3316,7 +3317,7 @@ class UriData {
buffer.write(";charset=");
buffer.write(_Uri._uriEncode(_tokenCharTable, charsetName, utf8, false));
}
parameters?.forEach((var key, var value) {
parameters?.forEach((key, value) {
if (key.isEmpty) {
throw new ArgumentError.value("", "Parameter names must not be empty");
}
+3 -2
View File
@@ -554,8 +554,9 @@ class Isolate {
StreamController controller;
RawReceivePort port;
void handleError(message) {
String errorDescription = message[0];
String stackDescription = message[1];
List listMessage = message;
String errorDescription = listMessage[0];
String stackDescription = listMessage[1];
var error = new RemoteError(errorDescription, stackDescription);
controller.addError(error, error.stackTrace);
}
+7 -3
View File
@@ -23,9 +23,13 @@ class Point<T extends num> {
* `other` is a `Point` with
* [x] equal to `other.x` and [y] equal to `other.y`.
*/
bool operator ==(other) {
if (other is! Point) return false;
return x == other.x && y == other.y;
bool operator ==(dynamic other) {
// Cannot change parameter type to `Object` in case some class
// inherits the type and uses their argument dynamically.
Object promotableOther = other;
return promotableOther is Point &&
x == promotableOther.x &&
y == promotableOther.y;
}
int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode);
+9 -6
View File
@@ -38,12 +38,15 @@ abstract class _RectangleBase<T extends num> {
return 'Rectangle ($left, $top) $width x $height';
}
bool operator ==(other) {
if (other is! Rectangle) return false;
return left == other.left &&
top == other.top &&
right == other.right &&
bottom == other.bottom;
bool operator ==(dynamic other) {
// Can't change argument type to `Object` since subclasses inherit it
// and uses their argument dynamically.
Object promotableOther = other;
return promotableOther is Rectangle &&
left == promotableOther.left &&
top == promotableOther.top &&
right == promotableOther.right &&
bottom == promotableOther.bottom;
}
int get hashCode => _JenkinsSmiHash.hash4(
@@ -68,12 +68,6 @@
"Dynamic invocation of 'call'.": 4,
"Dynamic invocation of 'then'.": 1
},
"org-dartlang-sdk:///sdk/lib/async/future.dart": {
"Dynamic invocation of 'call'.": 1
},
"org-dartlang-sdk:///sdk/lib/async/stream.dart": {
"Dynamic invocation of 'dart.async::_addError'.": 1
},
"org-dartlang-sdk:///sdk/lib/async/async_error.dart": {
"Dynamic invocation of 'call'.": 1
},
@@ -90,10 +84,6 @@
"Dynamic access of 'dart.collection::_element'.": 1,
"Dynamic access of 'dart.collection::_first'.": 1
},
"org-dartlang-sdk:///sdk/lib/collection/iterable.dart": {
"Dynamic access of 'length'.": 2,
"Dynamic invocation of '+'.": 2
},
"org-dartlang-sdk:///sdk/lib/html/dart2js/html_dart2js.dart": {
"Dynamic access of 'style'.": 1,
"Dynamic access of 'left'.": 3,
@@ -219,45 +209,15 @@
"Dynamic invocation of '-'.": 1,
"Dynamic invocation of '>='.": 1
},
"org-dartlang-sdk:///sdk/lib/core/duration.dart": {
"Dynamic access of 'dart.core::_duration'.": 1
},
"org-dartlang-sdk:///sdk/lib/core/errors.dart": {
"Dynamic access of 'length'.": 2,
"Dynamic invocation of '<'.": 1
},
"org-dartlang-sdk:///sdk/lib/core/exceptions.dart": {
"Dynamic access of 'length'.": 3,
"Dynamic invocation of 'codeUnitAt'.": 2,
"Dynamic invocation of 'substring'.": 1
},
"org-dartlang-sdk:///sdk/lib/core/uri.dart": {
"Dynamic access of 'isEmpty'.": 1,
"Dynamic invocation of 'startsWith'.": 1,
"Dynamic invocation of 'add'.": 1
},
"org-dartlang-sdk:///sdk/lib/math/point.dart": {
"Dynamic access of 'x'.": 1,
"Dynamic access of 'y'.": 1
},
"org-dartlang-sdk:///sdk/lib/math/rectangle.dart": {
"Dynamic access of 'left'.": 1,
"Dynamic access of 'top'.": 1,
"Dynamic access of 'right'.": 1,
"Dynamic access of 'bottom'.": 1
"Dynamic access of 'length'.": 2
},
"org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/convert_patch.dart": {
"Dynamic invocation of 'clear'.": 1
},
"org-dartlang-sdk:///sdk/lib/convert/encoding.dart": {
"Dynamic invocation of 'write'.": 1
},
"org-dartlang-sdk:///sdk/lib/convert/json.dart": {
"Dynamic invocation of 'toJson'.": 1
},
"org-dartlang-sdk:///sdk/lib/isolate/isolate.dart": {
"Dynamic invocation of '[]'.": 2
},
"org-dartlang-sdk:///sdk/lib/_http/crypto.dart": {
"Dynamic invocation of '+'.": 2,
"Dynamic invocation of '&'.": 3,