Revert "Fail synchronously if null is passed as an error to async APIs."

This reverts commit bef363bfb7.

Reason for revert: Breaks google3 tests, see b/151204525.

Original change's description:
> Fail synchronously if null is passed as an error to async APIs.
> 
> The first patchset is Lasse's original changes.
> 
> Change-Id: Ic5f24bcfc0ef4e82edee68d61e015b095cb5916e
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138605
> Reviewed-by: Leaf Petersen <leafp@google.com>

TBR=leafp@google.com,rnystrom@google.com

Change-Id: Ie17c35e9d23c70a7aecd1ef292962154cf6f007d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138925
Reviewed-by: David Morgan <davidmorgan@google.com>
Commit-Queue: David Morgan <davidmorgan@google.com>
This commit is contained in:
David Morgan 2020-03-11 10:07:49 +00:00 committed by commit-bot@chromium.org
parent e6a1e70960
commit a5bf30c401
27 changed files with 31 additions and 160 deletions

View file

@ -115,7 +115,6 @@ class _WebSocketProtocolTransformer extends StreamTransformerBase<List<int>,
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
_eventSink.addError(error, stackTrace);
}
@ -724,7 +723,6 @@ class _WebSocketOutgoingTransformer
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
_eventSink.addError(error, stackTrace);
}

View file

@ -419,7 +419,6 @@ class _AsyncStarImpl<T> {
}
void addError(Object error, StackTrace stackTrace) {
ArgumentError.checkNotNull(error, "error");
if (cancellationCompleter != null && !cancellationCompleter.isCompleted) {
// If the stream has been cancelled, complete the cancellation future
// with the error.

View file

@ -209,7 +209,6 @@ class _AsyncStarStreamController<T> {
}
void addError(Object error, StackTrace stackTrace) {
ArgumentError.checkNotNull(error, "error");
if ((cancellationFuture != null) && cancellationFuture._mayComplete) {
// If the stream has been cancelled, complete the cancellation future
// with the error.

View file

@ -253,7 +253,7 @@ abstract class _BroadcastStreamController<T>
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
error = _nonNullError(error);
if (!_mayAddEvent) throw _addEventError();
AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {
@ -480,7 +480,6 @@ class _AsBroadcastStreamController<T> extends _SyncBroadcastStreamController<T>
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
if (!isClosed && _isFiring) {
_addPendingEvent(new _DelayedError(error, stackTrace));
return;

View file

@ -266,12 +266,12 @@ abstract class Future<T> {
* If an error handler isn't added before the future completes, the error
* will be considered unhandled.
*
* The [error] must not be `null`.
* If [error] is `null`, it is replaced by a [NullThrownError].
*
* Use [Completer] to create a future and complete it later.
*/
factory Future.error(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
error = _nonNullError(error);
if (!identical(Zone.current, _rootZone)) {
AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {
@ -874,7 +874,7 @@ abstract class Completer<T> {
* Completing a future with an error indicates that an exception was thrown
* while trying to produce a value.
*
* The [error] must not be `null`.
* If [error] is `null`, it is replaced by a [NullThrownError].
*
* If `error` is a `Future`, the future itself is used as the error value.
* If you want to complete with the result of the future, you can use:

View file

@ -19,7 +19,7 @@ abstract class _Completer<T> implements Completer<T> {
void complete([FutureOr<T> value]);
void completeError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
error = _nonNullError(error);
if (!future._mayComplete) throw new StateError("Future already completed");
AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {
@ -94,8 +94,8 @@ class _FutureListener<S, T> {
this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
: callback = onValue,
errorCallback = errorCallback,
state = ((errorCallback == null) ? stateThen : stateThenOnerror) |
stateIsAwait;
state = ((errorCallback == null) ? stateThen : stateThenOnerror)
| stateIsAwait ;
_FutureListener.catchError(this.result, this.errorCallback, this.callback)
: state = (callback == null) ? stateCatcherror : stateCatcherrorTest;
@ -293,7 +293,8 @@ class _Future<T> implements Future<T> {
/// The system created liseners are not registered in the zone,
/// and the listener is marked as being from an `await`.
/// This marker is used in [_continuationFunctions].
Future<E> _thenAwait<E>(FutureOr<E> f(T value), Function onError) {
Future<E> _thenAwait<E>(
FutureOr<E> f(T value), Function onError) {
_Future<E> result = new _Future<E>();
_addListener(new _FutureListener<T, E>.thenAwait(result, f, onError));
return result;
@ -811,5 +812,5 @@ Function _registerErrorHandler(Function errorHandler, Zone zone) {
errorHandler,
"onError",
"Error handler must accept one Object or one Object and a StackTrace"
" as arguments, and return a a valid result");
" as arguments, and return a a valid result");
}

View file

@ -132,7 +132,6 @@ abstract class Stream<T> {
*
* This stream emits a single error event of [error] and [stackTrace]
* and then completes with a done event.
* The [error] must not be `null`.
*
* Example:
* ```dart
@ -153,13 +152,11 @@ abstract class Stream<T> {
* stack trace as well.
*/
@Since("2.5")
factory Stream.error(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
return (_AsyncStreamController<T>(null, null, null, null)
.._addError(error, stackTrace)
.._closeUnchecked())
.stream;
}
factory Stream.error(Object error, [StackTrace stackTrace]) =>
(_AsyncStreamController<T>(null, null, null, null)
.._addError(error, stackTrace)
.._closeUnchecked())
.stream;
/**
* Creates a new single-subscription stream from the future.
@ -1814,8 +1811,6 @@ abstract class EventSink<T> implements Sink<T> {
/**
* Adds an [error] to the sink.
*
* The [error] must not be `null`.
*
* Must not be called on a closed sink.
*/
void addError(Object error, [StackTrace stackTrace]);

View file

@ -237,7 +237,7 @@ abstract class StreamController<T> implements StreamSink<T> {
/**
* Sends or enqueues an error event.
*
* The [error] must not be `null`.
* If [error] is `null`, it is replaced by a [NullThrownError].
*
* Listeners receive this event at a later microtask. This behavior can be
* overridden by using `sync` controllers. Note, however, that sync
@ -361,8 +361,6 @@ abstract class SynchronousStreamController<T> implements StreamController<T> {
/**
* Adds error to the controller's stream.
*
* The [error] must not be `null`.
*
* As [StreamController.addError], but must not be called while an event is
* being added by [add], [addError] or [close].
*/
@ -599,11 +597,8 @@ abstract class _StreamController<T> implements _StreamControllerBase<T> {
/**
* Send or enqueue an error event.
*
* The [error] must not be `null`.
*/
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
if (!_mayAddEvent) throw _badEventState();
error = _nonNullError(error);
AsyncError replacement = Zone.current.errorCallback(error, stackTrace);

View file

@ -234,7 +234,6 @@ class _HandlerEventSink<S, T> implements EventSink<S> {
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
if (_isClosed) {
throw StateError("Sink is closed");
}

View file

@ -43,9 +43,7 @@ class AsyncError implements Error {
final Object error;
final StackTrace stackTrace;
AsyncError(this.error, this.stackTrace) {
ArgumentError.checkNotNull(error, "error");
}
AsyncError(this.error, this.stackTrace);
String toString() => '$error';
}
@ -752,7 +750,6 @@ class _ZoneDelegate implements ZoneDelegate {
}
AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) {
ArgumentError.checkNotNull(error, "error");
var implementation = _delegationTarget._errorCallback;
_Zone implZone = implementation.zone;
if (identical(implZone, _rootZone)) return null;
@ -1068,7 +1065,6 @@ class _CustomZone extends _Zone {
}
AsyncError errorCallback(Object error, StackTrace stackTrace) {
ArgumentError.checkNotNull(error, "error");
var implementation = this._errorCallback;
assert(implementation != null);
final Zone implementationZone = implementation.zone;
@ -1113,11 +1109,8 @@ class _CustomZone extends _Zone {
void _rootHandleUncaughtError(
Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
if (error == null) {
error = ArgumentError.notNull("error");
stackTrace = StackTrace.current;
}
_schedulePriorityAsyncCallback(() {
error ??= new NullThrownError();
if (stackTrace == null) throw error;
_rethrow(error, stackTrace);
});

View file

@ -75,7 +75,6 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> {
}
void addError(Object error, [StackTrace stackTrace]) {
ArgumentError.checkNotNull(error, "error");
_eventSink.addError(error, stackTrace);
}

View file

@ -113,8 +113,6 @@ class _WebSocketProtocolTransformer extends StreamTransformerBase<List<int>,
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
_eventSink!.addError(error, stackTrace);
}
@ -724,8 +722,6 @@ class _WebSocketOutgoingTransformer
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
_eventSink!.addError(error, stackTrace);
}
@ -1220,7 +1216,6 @@ class _WebSocketImpl extends Stream with _ServiceObject implements WebSocket {
}
void addUtf8Text(List<int> bytes) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(bytes, "bytes");
_sink.add(new _EncodedString(bytes));
}

View file

@ -417,7 +417,6 @@ class _AsyncStarImpl<T> {
}
void addError(Object error, StackTrace stackTrace) {
ArgumentError.checkNotNull(error, "error");
var completer = cancellationCompleter;
if (completer != null && !completer.isCompleted) {
// If the stream has been cancelled, complete the cancellation future

View file

@ -214,8 +214,6 @@ class _AsyncStarStreamController<T> {
}
void addError(Object error, StackTrace stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
final future = cancellationFuture;
if ((future != null) && future._mayComplete) {
// If the stream has been cancelled, complete the cancellation future

View file

@ -248,8 +248,6 @@ abstract class _BroadcastStreamController<T>
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
if (!_mayAddEvent) throw _addEventError();
AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {
@ -478,8 +476,6 @@ class _AsBroadcastStreamController<T> extends _SyncBroadcastStreamController<T>
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
if (!isClosed && _isFiring) {
_addPendingEvent(new _DelayedError(error, stackTrace));
return;

View file

@ -269,11 +269,11 @@ abstract class Future<T> {
* If an error handler isn't added before the future completes, the error
* will be considered unhandled.
*
* If [error] is `null`, it is replaced by a [NullThrownError].
*
* Use [Completer] to create a future and complete it later.
*/
factory Future.error(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
if (!identical(Zone.current, _rootZone)) {
AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {

View file

@ -17,8 +17,6 @@ abstract class _Completer<T> implements Completer<T> {
void complete([FutureOr<T>? value]);
void completeError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
if (!future._mayComplete) throw new StateError("Future already completed");
AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {

View file

@ -150,14 +150,11 @@ abstract class Stream<T> {
* stack trace as well.
*/
@Since("2.5")
factory Stream.error(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
return (_AsyncStreamController<T>(null, null, null, null)
.._addError(error, stackTrace)
.._closeUnchecked())
.stream;
}
factory Stream.error(Object error, [StackTrace? stackTrace]) =>
(_AsyncStreamController<T>(null, null, null, null)
.._addError(error, stackTrace)
.._closeUnchecked())
.stream;
/**
* Creates a new single-subscription stream from the future.

View file

@ -600,8 +600,6 @@ abstract class _StreamController<T> implements _StreamControllerBase<T> {
* Send or enqueue an error event.
*/
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
if (!_mayAddEvent) throw _badEventState();
AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {

View file

@ -229,8 +229,6 @@ class _HandlerEventSink<S, T> implements EventSink<S> {
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
var sink = _sink;
if (sink == null) {
throw StateError("Sink is closed");

View file

@ -41,10 +41,7 @@ class AsyncError implements Error {
final Object error;
final StackTrace? stackTrace;
AsyncError(this.error, this.stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
}
AsyncError(this.error, this.stackTrace);
String toString() => '$error';
}
@ -745,8 +742,6 @@ class _ZoneDelegate implements ZoneDelegate {
}
AsyncError? errorCallback(Zone zone, Object error, StackTrace? stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
var implementation = _delegationTarget._errorCallback;
_Zone implZone = implementation.zone;
if (identical(implZone, _rootZone)) return null;
@ -1080,8 +1075,6 @@ class _CustomZone extends _Zone {
}
AsyncError? errorCallback(Object error, StackTrace? stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
var implementation = this._errorCallback;
final _Zone implementationZone = implementation.zone;
if (identical(implementationZone, _rootZone)) return null;

View file

@ -73,8 +73,6 @@ class _ConverterStreamEventSink<S, T> implements EventSink<S> {
}
void addError(Object error, [StackTrace? stackTrace]) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
_eventSink.addError(error, stackTrace);
}

View file

@ -1,13 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:expect/expect.dart';
main() {
// The error cannot be null.
Expect.throwsArgumentError(() {
Future.error(null);
});
}

View file

@ -697,10 +697,13 @@ void testCompleteErrorWithCustomFuture() {
}
void testCompleteErrorWithNull() {
asyncStart();
final completer = new Completer<int>();
Expect.throwsArgumentError(() {
completer.completeError(null);
completer.future.catchError((e) {
Expect.isTrue(e is NullThrownError);
asyncEnd();
});
completer.completeError(null);
}
void testChainedFutureValue() {

View file

@ -1,48 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:expect/expect.dart';
main() {
// Single-cast async.
var controller = StreamController();
Expect.throwsArgumentError(() {
controller.addError(null);
});
Expect.throwsArgumentError(() {
controller.sink.addError(null);
});
// Single-cast sync.
controller = StreamController(sync: true);
Expect.throwsArgumentError(() {
controller.addError(null);
});
Expect.throwsArgumentError(() {
controller.sink.addError(null);
});
// Broadcast async.
controller = StreamController.broadcast();
Expect.throwsArgumentError(() {
controller.addError(null);
});
Expect.throwsArgumentError(() {
controller.sink.addError(null);
});
// Broadcast sync.
controller = StreamController.broadcast(sync: true);
Expect.throwsArgumentError(() {
controller.addError(null);
});
Expect.throwsArgumentError(() {
controller.sink.addError(null);
});
}

View file

@ -72,11 +72,6 @@ void main() async {
await onDone.future;
}
// A null error argument is a synchronous error.
Expect.throwsArgumentError(() {
Stream.error(null);
});
asyncEnd();
}

View file

@ -1,13 +0,0 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:expect/expect.dart';
main() {
// The error cannot be null.
Expect.throwsArgumentError(() {
AsyncError(null, StackTrace.current);
});
}