diff --git a/Language/Statements/For/Asynchronous_For_in/enclosing_loop_t01.dart b/Language/Statements/For/Asynchronous_For_in/enclosing_loop_t01.dart index 3ce950a60e..8e0b4fef23 100644 --- a/Language/Statements/For/Asynchronous_For_in/enclosing_loop_t01.dart +++ b/Language/Statements/For/Asynchronous_For_in/enclosing_loop_t01.dart @@ -14,7 +14,6 @@ import 'dart:async'; import '../../../../Utils/expect.dart'; - Future test1() async { List log = []; StreamController streamController = new StreamController(); @@ -33,7 +32,6 @@ Future test1() async { Expect.listEquals(['a', 'a1', 'a2', '1', '11', '12', '2', '21', '22'], log); } - Future test2() async { List log = []; StreamController streamController = new StreamController(); @@ -47,7 +45,7 @@ Future test2() async { } else if (!streamController.isClosed) { streamController.close(); } - await new Future.delayed(new Duration(microseconds: 100)); + await null; } } Expect.listEquals(['a', 'a1', 'a2', '1', '11', '12', '2', '21', '22'], log); diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A01_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A01_t01.dart new file mode 100644 index 0000000000..f22d88727d --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A01_t01.dart @@ -0,0 +1,73 @@ +// Copyright (c) 2015, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that a compile error occurs if o is not an instance +/// of a class that implements [Stream] +/// +/// @author a.semenov@unipro.ru + +import 'dart:async'; + +Future test1() async { + await for (var i in new Object()) { +// ^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +Future test2() async { + await for (int i in [1, 2, 3]) { +// ^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +main() { + test1(); + test2(); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A01_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_A01_t02.dart new file mode 100644 index 0000000000..11f86bec4f --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A01_t02.dart @@ -0,0 +1,66 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that it is a dynamic type error if `o` is not an instance +/// of a class that implements [Stream] +/// +/// @author sgrekhov22@gmail.com + +import '../../../../Utils/expect.dart'; + +main() async { + bool wasException = false; + dynamic collection = [1, 2, 3]; + try { + await for (var i in collection) { + Expect.fail("Dynamic error expected"); + print(i); + } + } catch (_) { + wasException = true; + } + Expect.isTrue(wasException); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A01_t03.dart b/Language/Statements/For/Asynchronous_For_in/execution_A01_t03.dart new file mode 100644 index 0000000000..e3a39b6a27 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A01_t03.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that it is a compile-time error if `D` is empty and id is +/// a final variable. +/// +/// @author sgrekhov22@gmail.com +/// @issue 49495 + +main() async { + final i; + await for (i in Stream.fromIterable(['one', 'two', 'three'])) { +// ^ +// [analyzer] unspecified +// [cfe] unspecified + } +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A02_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A02_t01.dart new file mode 100644 index 0000000000..a4c34cbea0 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A02_t01.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that the stream associated with the innermost enclosing +/// asynchronous for loop is paused +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + StreamController sc = StreamController(); + sc.addStream(Stream.fromIterable([1, 2, 3])); + await for (var i in sc.stream) { + await for (var j in Stream.fromIterable(['one', 'two', 'three'])) { + Expect.isTrue(sc.isPaused); + } + } +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A02_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_A02_t02.dart new file mode 100644 index 0000000000..5655cc6371 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A02_t02.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that execution of the asynchronous for-in loop is +/// suspended until a stream event is available but not paused +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + StreamController sc = StreamController(); + sc.addStream(Stream.fromIterable([1, 2, 3])); + await for (var j in Stream.fromIterable(['one', 'two', 'three'])) { + await for (var i in sc.stream) { + Expect.isFalse(sc.isPaused); + } + } +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A03_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A03_t01.dart new file mode 100644 index 0000000000..e5934148fe --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A03_t01.dart @@ -0,0 +1,82 @@ +// Copyright (c) 2015, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that for each data event from `u`, the statement `s` is +/// executed with `id` bound to the value of the current data event. +/// +/// @author a.semenov@unipro.ru + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +Future test1() async { + var processedValues = []; + await for (var i in new Stream.fromIterable([1, 2, 3])) { + processedValues.add(i); + } + Expect.listEquals([1, 2, 3], processedValues); +} + +Future test2() async { + var processedValues = []; + await for (var i in new Stream.fromIterable(['a', 'b' ,'c'])) { + processedValues.add(i); + } + Expect.listEquals(['a', 'b', 'c'], processedValues); +} + +Future test3() async { + var processedValues = []; + await for (var i in new Stream.empty()) { + processedValues.add(i); + } + Expect.listEquals([], processedValues); +} + +main() { + asyncStart(); + Future.wait([test1(), test2(), test3()]).then((v) => asyncEnd()); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A04_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A04_t01.dart new file mode 100644 index 0000000000..41239c0015 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A04_t01.dart @@ -0,0 +1,64 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if execution of `s` continues without a label then +/// the execution of `s` is treated as if it had completed normally +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + List log = []; + await for(var i in Stream.fromIterable([1, 2, 3, 4, 5])) { + if (i.isEven) { + continue; + } + log.add(i); + } + Expect.listEquals([1, 3, 5], log); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A04_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_A04_t02.dart new file mode 100644 index 0000000000..2b73a94dc1 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A04_t02.dart @@ -0,0 +1,65 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if execution of `s` continues to a label that +/// prefixes the asynchronous for statement then the execution of `s` is treated +/// as if it had completed normally +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + List log = []; + Label1: await for(var i in Stream.fromIterable([1, 2, 3, 4, 5])) { + if (i.isEven) { + continue Label1; + } + log.add(i); + } + Expect.listEquals([1, 3, 5], log); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A05_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A05_t01.dart new file mode 100644 index 0000000000..12a773e393 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A05_t01.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if execution of `s` does not complete normally, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. Test the case when +/// execution of `await for-in` was interrupted by `break` +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + asyncStart(); + List log = []; + StreamController sc = StreamController(onCancel: () { + Expect.listEquals([1, 2, 3], log); + asyncEnd(); + }); + sc.addStream(Stream.fromIterable([1, 2, 3, 4, 5])); + await for(var i in sc.stream) { + log.add(i); + if (i == 3) { + break; + } + } +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A05_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_A05_t02.dart new file mode 100644 index 0000000000..9ed3522d91 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A05_t02.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if execution of `s` does not complete normally, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. Test the case when +/// execution of `await for-in` was interrupted by `continue` to a label outside +/// of the loop +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + asyncStart(); + List log = []; + StreamController sc = StreamController(onCancel: () { + Expect.listEquals([1, 2, 3], log); + asyncEnd(); + }); + sc.addStream(Stream.fromIterable([1, 2, 3, 4, 5])); + Label1: + await for (var i in Stream.fromIterable([42])) { + await for (var j in sc.stream) { + log.add(j); + if (j == 3) { + continue Label1; + } + } + } +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A05_t03.dart b/Language/Statements/For/Asynchronous_For_in/execution_A05_t03.dart new file mode 100644 index 0000000000..556e2a4036 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A05_t03.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2015, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if s raises an exception, then asynchronous for-in +/// statement is completed with that exception. +/// @author a.semenov@unipro.ru + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +final ERROR = new Exception(); + +Future test1() async { + var processedValues = []; + try { + await for (var i in new Stream.fromIterable([1, 2])) { + processedValues.add(i); + throw ERROR; + } + Expect.fail("Asynchronous for-in statement should throw $ERROR"); + } catch (e) { + Expect.identical(ERROR, e); + } + Expect.listEquals([1], processedValues); +} + +Future test2() async { + var processedValues = []; + try { + await for (int i in new Stream.empty()) { + processedValues.add(i); + throw ERROR; + } + Expect.listEquals([], processedValues); + } catch (e) { + Expect.fail("Asynchronous for-in statement should not throw $e " + + "for empty stream"); + } +} + +main() { + asyncStart(); + Future.wait([test1(), test2()]).then((v) => asyncEnd()); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A05_t04.dart b/Language/Statements/For/Asynchronous_For_in/execution_A05_t04.dart new file mode 100644 index 0000000000..81c0331fb8 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A05_t04.dart @@ -0,0 +1,124 @@ +// Copyright (c) 2015, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that if o raises an exception, then asynchronous for-in +/// statement is completed with that exception. +/// +/// @issue 24766 +/// @issue 24748 +/// @author a.semenov@unipro.ru + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +final ERROR = new Exception(); + +Future f() async { + throw ERROR; +} + +Future test1() async { + var processedValues = []; + try { + await for (var i in f().asStream()) { + processedValues.add(i); + } + Expect.fail("Asynchronous for-in statement should throw $ERROR"); + } catch (e) { + Expect.identical(ERROR, e); + } + Expect.listEquals([], processedValues); +} + +int computation(int computationCount) { + if (computationCount < 5) { + return computationCount; + } + throw ERROR; +} + +Future test2() async { + var processedValues = []; + var period = new Duration(microseconds: 1); + try { + await for (var i in new Stream.periodic(period, computation)) { + processedValues.add(i); + } + Expect.fail("Asynchronous for-in statement should throw $ERROR"); + } catch (e) { + Expect.identical(ERROR, e); + } + Expect.listEquals([0, 1, 2, 3, 4], processedValues); +} + +// try an already closed single subscription stream +Future test3() async { + Stream generator() async* { + yield 42; + } + Stream stream = generator(); + await for (var i in stream) { + } + var processedValues = []; + try { + await for (var i in stream) { + processedValues.add(i); + } + Expect.fail("Asynchronous for-in statement should complete with error"); + } catch (e) { + // the exception type is not specified + // neither in Dart Language Specification nor in Dart Async API + // (see issue 24748) + // so just catch it + } + Expect.isTrue(processedValues.isEmpty); +} + + +main() { + asyncStart(); + Future.wait([test1(), test2(), test3()]).then((v) => asyncEnd()); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A05_t05.dart b/Language/Statements/For/Asynchronous_For_in/execution_A05_t05.dart new file mode 100644 index 0000000000..ec31677b1c --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A05_t05.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that the execution of `f` is suspended again, waiting for +/// the next stream subscription event, and `u` is resumed if it has been paused +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + asyncStart(); + List log = []; + bool visited = false; + StreamController sc = StreamController(); + sc.addStream(Stream.fromIterable([1, 2, 3])).then((_) async { + Expect.listEquals([1, 2, 3], log); + await null; + sc.add(42); // await for is suspended now + Expect.listEquals([1, 2, 3], log); + await null; + Expect.listEquals([1, 2, 3, 42], log); + visited = true; + await sc.close(); + }); + await for (var i in sc.stream) { + log.add(i); + } + Expect.isTrue(visited); + asyncEnd(); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A06_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A06_t01.dart new file mode 100644 index 0000000000..2065f78717 --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A06_t01.dart @@ -0,0 +1,79 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that on an error event from `u`, with error object `e` +/// subscription `u` is canceled +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + asyncStart(); + List log = []; + bool visited = false; + StreamController sc = StreamController(onCancel: () { + Expect.listEquals([1, 2], log); + visited = true; + }); + sc.add(1); + sc.add(2); + sc.addError("Error!"); + sc.add(3); + await null; + + try { + await for (var i in sc.stream) { + log.add(i); + } + } catch (e) { + Expect.equals("Error!", e); + Expect.isTrue(visited); + asyncEnd(); + } +} + diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A06_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_A06_t02.dart new file mode 100644 index 0000000000..7c9456a92a --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A06_t02.dart @@ -0,0 +1,82 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that on an error event from `u`, with error object `e` +/// and stack trace `st` subscription `u` is canceled +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +main() async { + asyncStart(); + List log = []; + bool visited = false; + StreamController sc = StreamController(onCancel: () { + Expect.listEquals([1, 2], log); + visited = true; + }); + sc.add(1); + sc.add(2); + final st = StackTrace.fromString("Stack Trace String"); + final e = new Exception("Error!"); + sc.addError(e, st); + sc.add(3); + await null; + + try { + await for (var i in sc.stream) { + log.add(i); + } + } catch (_e, _st) { + Expect.equals(e, _e); + Expect.equals(st, _st); + Expect.isTrue(visited); + asyncEnd(); + } +} + diff --git a/Language/Statements/For/Asynchronous_For_in/execution_A07_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_A07_t01.dart new file mode 100644 index 0000000000..fae7f0041b --- /dev/null +++ b/Language/Statements/For/Asynchronous_For_in/execution_A07_t01.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2022, 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. + +/// @assertion Let `D` be derived from ?. Execution of a +/// for-in statement, `f`, of the form `await for (D id in e) s` proceeds as +/// follows: +/// +/// The expression `e` is evaluated to an object `o`. It is a dynamic type error +/// if `o` is not an instance of a class that implements [Stream]. It is a +/// compile-time error if `D` is empty and `id` is a final variable. +/// +/// The stream associated with the innermost enclosing asynchronous for loop, +/// if any, is paused. The stream `o` is listened to, producing a stream +/// subscription `u`, and execution of the asynchronous for-in loop is suspended +/// until a stream event is available. +/// +/// Pausing an asynchronous for loop means pausing the associated stream +/// subscription. A stream subscription is paused by calling its pause method. +/// If the subscription is already paused, an implementation may omit further +/// calls to pause. +/// +/// For each data event from `u`, the statement `s` is executed with `id` bound +/// to the value of the current data event. +/// +/// If execution of `s` continues without a label, or to a label that prefixes +/// the asynchronous for statement, then the execution of `s` is treated as if +/// it had completed normally. +/// +/// If execution of `s` otherwise does not complete normally, the subscription +/// `u` is canceled by evaluating `await v.cancel()` where `v` is a fresh +/// variable referencing the stream subscription `u`. If that evaluation throws, +/// execution of `f` throws the same exception and stack trace. Otherwise +/// execution of `f` completes in the same way as the execution of `s`. +/// Otherwise the execution of `f` is suspended again, waiting for the next +/// stream subscription event, and `u` is resumed if it has been paused. +/// +/// On an error event from `u`, with error object `e` and stack trace `st`, the +/// subscription `u` is canceled by evaluating `await v.cancel()` where `v` is a +/// fresh variable referencing the stream subscription `u`. If that evaluation +/// throws, execution of `f` throws the same exception object and stack trace. +/// Otherwise execution of `f` throws with `e` as exception object and `st` as +/// stack trace. +/// +/// When `u` is done, execution of `f` completes normally. +/// +/// @description Check that when `u` is done, execution of `f` completes +/// normally. +/// +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../../Utils/expect.dart'; + +Stream generator() async* { + for (int i = 0; i < 5; i++) { + yield i; + } +} + +main() async { + asyncStart(); + List log = []; + await for(var i in generator()) { + log.add(i); + } + Expect.listEquals([0, 1, 2, 3, 4], log); + log.clear(); + await for(var i in Stream.fromIterable([3, 1, 4, 1, 5])) { + log.add(i); + } + Expect.listEquals([3, 1, 4, 1, 5], log); + asyncEnd(); +} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_t01.dart b/Language/Statements/For/Asynchronous_For_in/execution_t01.dart deleted file mode 100644 index 6e8e3cc327..0000000000 --- a/Language/Statements/For/Asynchronous_For_in/execution_t01.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2015, 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. - -/// @assertion Execution of a for-in statement of the form await for -/// (finalConstVarOrType? id in e) s proceeds as follows: -/// The expression e is evaluated to an object o. It is a dynamic error if o -/// is not an instance of a class that implements Stream. Otherwise, -/// the expression await vf is evaluated, where vf is a fresh variable -/// whose value is a fresh instance f implementing the built-in class Future. -/// The stream o is listened to, and on each data event in o -/// the statement s is executed with id bound to the value of the current -/// element of the stream. If s raises an exception, or if o raises -/// an exception, then f is completed with that exception. Otherwise, when -/// all events in the stream o have been processed, f is completed with null. -/// -/// @description Check that a compile error occurs if o is not an instance -/// of a class that implements Stream -/// @author a.semenov@unipro.ru - -import 'dart:async'; -import '../../../../Utils/expect.dart'; - -Future test1() async { - await for (var i in new Object()) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - } -} - -main() { - asyncStart(); - test1().then( - (value) => Expect.fail("Compile error is expected"), - onError: (error) => asyncEnd() - // TODO verify that error is a compile error - ); -} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_t02.dart b/Language/Statements/For/Asynchronous_For_in/execution_t02.dart deleted file mode 100644 index d481e2671c..0000000000 --- a/Language/Statements/For/Asynchronous_For_in/execution_t02.dart +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2015, 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. - -/// @assertion Execution of a for-in statement of the form await for -/// (finalConstVarOrType? id in e) s proceeds as follows: -/// The expression e is evaluated to an object o. It is a dynamic error if o -/// is not an instance of a class that implements Stream. Otherwise, -/// the expression await vf is evaluated, where vf is a fresh variable -/// whose value is a fresh instance f implementing the built-in class Future. -/// The stream o is listened to, and on each data event in o -/// the statement s is executed with id bound to the value of the current -/// element of the stream. If s raises an exception, or if o raises -/// an exception, then f is completed with that exception. Otherwise, when -/// all events in the stream o have been processed, f is completed with null. -/// -/// @description Check that on each data event in o the statement s is -/// executed with id bound to the value of the current element of the stream. -/// -/// @author a.semenov@unipro.ru - -import 'dart:async'; -import '../../../../Utils/expect.dart'; - -Future test1() async { - var processedValues = []; - await for (var i in new Stream.fromIterable([1, 2, 3])) { - processedValues.add(i); - } - Expect.listEquals([1, 2, 3], processedValues); -} - -Future test2() async { - var processedValues = []; - await for (var i in new Stream.fromIterable(['a', 'b' ,'c'])) { - processedValues.add(i); - } - Expect.listEquals(['a', 'b', 'c'], processedValues); -} - -Future test3() async { - var processedValues = []; - await for (var i in new Stream.empty()) { - processedValues.add(i); - } - Expect.listEquals([], processedValues); -} - -main() { - asyncStart(); - Future.wait([test1(), test2(), test3()]).then((v) => asyncEnd()); -} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_t03.dart b/Language/Statements/For/Asynchronous_For_in/execution_t03.dart deleted file mode 100644 index d8e831ea94..0000000000 --- a/Language/Statements/For/Asynchronous_For_in/execution_t03.dart +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2015, 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. - -/// @assertion Execution of a for-in statement of the form await for -/// (finalConstVarOrType? id in e) s proceeds as follows: -/// The expression e is evaluated to an object o. It is a dynamic error if o -/// is not an instance of a class that implements Stream. Otherwise, -/// the expression await vf is evaluated, where vf is a fresh variable -/// whose value is a fresh instance f implementing the built-in class Future. -/// The stream o is listened to, and on each data event in o -/// the statement s is executed with id bound to the value of the current -/// element of the stream. If s raises an exception, or if o raises -/// an exception, then f is completed with that exception. Otherwise, when -/// all events in the stream o have been processed, f is completed with null. -/// -/// @description Check that if s raises an exception, then asynchronous for-in -/// statement is completed with that exception. -/// @author a.semenov@unipro.ru - -import 'dart:async'; -import '../../../../Utils/expect.dart'; - -final ERROR = new Exception(); - -Future test1() async { - var processedValues = []; - try { - await for (var i in new Stream.fromIterable([1, 2])) { - processedValues.add(i); - throw ERROR; - } - Expect.fail("Asynchronous for-in statement should throw $ERROR"); - } catch (e) { - Expect.identical(ERROR, e); - } - Expect.listEquals([1], processedValues); -} - -Future test2() async { - var processedValues = []; - try { - await for (int i in new Stream.empty()) { - processedValues.add(i); - throw ERROR; - } - Expect.listEquals([], processedValues); - } catch (e) { - Expect.fail("Asynchronous for-in statement should not throw $e " + - "for empty stream"); - } -} - -main() { - asyncStart(); - Future.wait([test1(), test2()]).then((v) => asyncEnd()); -} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_t04.dart b/Language/Statements/For/Asynchronous_For_in/execution_t04.dart deleted file mode 100644 index 4ec8ffd00f..0000000000 --- a/Language/Statements/For/Asynchronous_For_in/execution_t04.dart +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2015, 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. - -/// @assertion Execution of a for-in statement of the form await for -/// (finalConstVarOrType? id in e) s proceeds as follows: -/// The expression e is evaluated to an object o. It is a dynamic error if o -/// is not an instance of a class that implements Stream. Otherwise, -/// the expression await vf is evaluated, where vf is a fresh variable -/// whose value is a fresh instance f implementing the built-in class Future. -/// The stream o is listened to, and on each data event in o -/// the statement s is executed with id bound to the value of the current -/// element of the stream. If s raises an exception, or if o raises -/// an exception, then f is completed with that exception. Otherwise, when -/// all events in the stream o have been processed, f is completed with null. -/// -/// @description Check that if o raises an exception, then asynchronous for-in -/// statement is completed with that exception. -/// -/// @issue 24766 -/// @issue 24748 -/// @author a.semenov@unipro.ru - -import 'dart:async'; -import '../../../../Utils/expect.dart'; - -final ERROR = new Exception(); - -Future f() async { - throw ERROR; -} - -Future test1() async { - var processedValues = []; - try { - await for (var i in f().asStream()) { - processedValues.add(i); - } - Expect.fail("Asynchronous for-in statement should throw $ERROR"); - } catch (e) { - Expect.identical(ERROR, e); - } - Expect.listEquals([], processedValues); -} - -int computation(int computationCount) { - if (computationCount < 5) { - return computationCount; - } - throw ERROR; -} - -Future test2() async { - var processedValues = []; - var period = new Duration(microseconds: 1); - try { - await for (var i in new Stream.periodic(period, computation)) { - processedValues.add(i); - } - Expect.fail("Asynchronous for-in statement should throw $ERROR"); - } catch (e) { - Expect.identical(ERROR, e); - } - Expect.listEquals([0, 1, 2, 3, 4], processedValues); -} - -// try an already closed single subscription stream -Future test3() async { - // make a stream that is closed - Stream stream = new Stream.fromIterable([1, 2]); - await for (var x in stream) { - } - var processedValues = []; - try { - await for (var i in stream) { - processedValues.add(i); - } - Expect.fail("Asynchronous for-in statement should complete with error"); - } catch (e) { - // the exception type is not specified - // neither in Dart Language Specification nor in Dart Async API - // (see issue 24748) - // so just catch it - } - Expect.isTrue(processedValues.isEmpty); -} - - -main() { - asyncStart(); - Future.wait([test1(), test2(), test3()]).then((v) => asyncEnd()); -} diff --git a/Language/Statements/For/Asynchronous_For_in/execution_t05.dart b/Language/Statements/For/Asynchronous_For_in/execution_t05.dart deleted file mode 100644 index 7123846935..0000000000 --- a/Language/Statements/For/Asynchronous_For_in/execution_t05.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2015, 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. - -/// @assertion Execution of a for-in statement of the form await for -/// (finalConstVarOrType? id in e) s proceeds as follows: -/// The expression e is evaluated to an object o. It is a dynamic error if o -/// is not an instance of a class that implements Stream. Otherwise, -/// the expression await vf is evaluated, where vf is a fresh variable -/// whose value is a fresh instance f implementing the built-in class Future. -/// The stream o is listened to, and on each data event in o -/// the statement s is executed with id bound to the value of the current -/// element of the stream. If s raises an exception, or if o raises -/// an exception, then f is completed with that exception. Otherwise, when -/// all events in the stream o have been processed, f is completed with null. -/// -/// @description Check that a compile error occurs if o is not an instance -/// of a class that implements Stream -/// @author a.semenov@unipro.ru - -import 'dart:async'; -import '../../../../Utils/expect.dart'; - -Future test2() async { - await for (int i in [1, 2, 3]) { -// ^ -// [analyzer] unspecified -// [cfe] unspecified - } -} - -main() { - asyncStart(); - test2().then( - (value) => Expect.fail("Compile error is expected"), - onError: (error) => asyncEnd() - // TODO verify that error is a compile error - ); -}