From d56a057cd1a4039ad70949238f4f500d069709f8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 16:41:33 -0800 Subject: [PATCH 001/138] Initial commit. --- pkgs/stream_channel/.gitignore | 9 ++++++++ pkgs/stream_channel/.test_config | 3 +++ pkgs/stream_channel/AUTHORS | 6 ++++++ pkgs/stream_channel/CHANGELOG.md | 3 +++ pkgs/stream_channel/CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++ pkgs/stream_channel/LICENSE | 26 +++++++++++++++++++++++ pkgs/stream_channel/README.md | 16 ++++++++++++++ pkgs/stream_channel/pubspec.yaml | 9 ++++++++ 8 files changed, 105 insertions(+) create mode 100644 pkgs/stream_channel/.gitignore create mode 100644 pkgs/stream_channel/.test_config create mode 100644 pkgs/stream_channel/AUTHORS create mode 100644 pkgs/stream_channel/CHANGELOG.md create mode 100644 pkgs/stream_channel/CONTRIBUTING.md create mode 100644 pkgs/stream_channel/LICENSE create mode 100644 pkgs/stream_channel/README.md create mode 100644 pkgs/stream_channel/pubspec.yaml diff --git a/pkgs/stream_channel/.gitignore b/pkgs/stream_channel/.gitignore new file mode 100644 index 0000000000..25a1df3326 --- /dev/null +++ b/pkgs/stream_channel/.gitignore @@ -0,0 +1,9 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +.packages +pubspec.lock diff --git a/pkgs/stream_channel/.test_config b/pkgs/stream_channel/.test_config new file mode 100644 index 0000000000..352d2feeec --- /dev/null +++ b/pkgs/stream_channel/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} diff --git a/pkgs/stream_channel/AUTHORS b/pkgs/stream_channel/AUTHORS new file mode 100644 index 0000000000..e8063a8cd6 --- /dev/null +++ b/pkgs/stream_channel/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md new file mode 100644 index 0000000000..847d60daa4 --- /dev/null +++ b/pkgs/stream_channel/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* Initial version diff --git a/pkgs/stream_channel/CONTRIBUTING.md b/pkgs/stream_channel/CONTRIBUTING.md new file mode 100644 index 0000000000..6f5e0ea67d --- /dev/null +++ b/pkgs/stream_channel/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/stream_channel/LICENSE b/pkgs/stream_channel/LICENSE new file mode 100644 index 0000000000..de31e1a0a4 --- /dev/null +++ b/pkgs/stream_channel/LICENSE @@ -0,0 +1,26 @@ +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md new file mode 100644 index 0000000000..5d6a2b4e04 --- /dev/null +++ b/pkgs/stream_channel/README.md @@ -0,0 +1,16 @@ +This package exposes the `StreamChannel` interface, which represents a two-way +communication channel. Each `StreamChannel` exposes a `Stream` for receiving +data and a `StreamSink` for sending it. + +`StreamChannel` helps abstract communication logic away from the underlying +protocol. For example, the [`test`][test] package re-uses its test suite +communication protocol for both WebSocket connections to browser suites and +Isolate connections to VM tests. + +[test]: https://pub.dartlang.org/packages/test + +This package also contains utilities for dealing with `StreamChannel`s and with +two-way communications in general. For documentation of these utilities, see +[the API docs][api]. + +[api]: https://www.dartdocs.org/documentation/stream_channel/latest diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml new file mode 100644 index 0000000000..76f22b7da5 --- /dev/null +++ b/pkgs/stream_channel/pubspec.yaml @@ -0,0 +1,9 @@ +name: stream_channel +version: 1.0.0-dev +description: An abstraction for two-way communication channels. +author: Dart Team +homepage: https://github.com/dart-lang/stream_channel +environment: + sdk: '>=1.0.0 <2.0.0' +dev_dependencies: + test: '^0.12.0' From d0b0d2d1150f7de04e3d4bfac27a238358197611 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 16:50:25 -0800 Subject: [PATCH 002/138] Add codereview.settings. --- pkgs/stream_channel/codereview.settings | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pkgs/stream_channel/codereview.settings diff --git a/pkgs/stream_channel/codereview.settings b/pkgs/stream_channel/codereview.settings new file mode 100644 index 0000000000..7b0a9edc6c --- /dev/null +++ b/pkgs/stream_channel/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: https://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/stream_channel/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From 3ee20be6a7e5baa85fd75c270faa2c3af528734d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 20 Jan 2016 17:02:20 -0800 Subject: [PATCH 003/138] Add StreamChannel and MultiChannel. These are exact copies of the classes and tests from the test package. R=rnystrom@google.com, kevmoo@google.com Review URL: https://codereview.chromium.org//1610443002 . --- .../stream_channel/lib/src/multi_channel.dart | 244 ++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 50 +++ .../test/multi_channel_test.dart | 310 ++++++++++++++++++ pkgs/stream_channel/test/utils.dart | 20 ++ 4 files changed, 624 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/multi_channel.dart create mode 100644 pkgs/stream_channel/lib/stream_channel.dart create mode 100644 pkgs/stream_channel/test/multi_channel_test.dart create mode 100644 pkgs/stream_channel/test/utils.dart diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart new file mode 100644 index 0000000000..e87deb33bc --- /dev/null +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -0,0 +1,244 @@ +// Copyright (c) 2016, 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 '../stream_channel.dart'; + +/// A class that multiplexes multiple virtual channels across a single +/// underlying transport layer. +/// +/// This should be connected to another [MultiChannel] on the other end of the +/// underlying channel. It starts with a single default virtual channel, +/// accessible via [stream] and [sink]. Additional virtual channels can be +/// created with [virtualChannel]. +/// +/// When a virtual channel is created by one endpoint, the other must connect to +/// it before messages may be sent through it. The first endpoint passes its +/// [VirtualChannel.id] to the second, which then creates a channel from that id +/// also using [virtualChannel]. For example: +/// +/// ```dart +/// // First endpoint +/// var virtual = multiChannel.virtualChannel(); +/// multiChannel.sink.add({ +/// "channel": virtual.id +/// }); +/// +/// // Second endpoint +/// multiChannel.stream.listen((message) { +/// var virtual = multiChannel.virtualChannel(message["channel"]); +/// // ... +/// }); +/// ``` +/// +/// Sending errors across a [MultiChannel] is not supported. Any errors from the +/// underlying stream will be reported only via the default +/// [MultiChannel.stream]. +/// +/// Each virtual channel may be closed individually. When all of them are +/// closed, the underlying [StreamSink] is closed automatically. +abstract class MultiChannel implements StreamChannel { + /// The default input stream. + /// + /// This connects to the remote [sink]. + Stream get stream; + + /// The default output stream. + /// + /// This connects to the remote [stream]. If this is closed, the remote + /// [stream] will close, but other virtual channels will remain open and new + /// virtual channels may be opened. + StreamSink get sink; + + /// Creates a new [MultiChannel] that sends messages over [innerStream] and + /// [innerSink]. + /// + /// The inner streams must take JSON-like objects. + factory MultiChannel(Stream innerStream, StreamSink innerSink) => + new _MultiChannel(innerStream, innerSink); + + /// Creates a new virtual channel. + /// + /// If [id] is not passed, this creates a virtual channel from scratch. Before + /// it's used, its [VirtualChannel.id] must be sent to the remote endpoint + /// where [virtualChannel] should be called with that id. + /// + /// If [id] is passed, this creates a virtual channel corresponding to the + /// channel with that id on the remote channel. + /// + /// Throws an [ArgumentError] if a virtual channel already exists for [id]. + /// Throws a [StateError] if the underlying channel is closed. + VirtualChannel virtualChannel([id]); +} + +/// The implementation of [MultiChannel]. +/// +/// This is private so that [VirtualChannel] can inherit from [MultiChannel] +/// without having to implement all the private members. +class _MultiChannel extends StreamChannelMixin implements MultiChannel { + /// The inner stream over which all communication is received. + /// + /// This will be `null` if the underlying communication channel is closed. + Stream _innerStream; + + /// The inner sink over which all communication is sent. + /// + /// This will be `null` if the underlying communication channel is closed. + StreamSink _innerSink; + + /// The subscription to [_innerStream]. + StreamSubscription _innerStreamSubscription; + + Stream get stream => _streamController.stream; + final _streamController = new StreamController(sync: true); + + StreamSink get sink => _sinkController.sink; + final _sinkController = new StreamController(sync: true); + + /// A map from virtual channel ids to [StreamController]s that should be used + /// to write messages received from those channels. + final _streamControllers = new Map(); + + /// A map from virtual channel ids to [StreamControllers]s that are used + /// to receive messages to write to those channels. + /// + /// Note that this uses the same keys as [_streamControllers]. + final _sinkControllers = new Map(); + + /// The next id to use for a local virtual channel. + /// + /// Ids are used to identify virtual channels. Each message is tagged with an + /// id; the receiving [MultiChannel] uses this id to look up which + /// [VirtualChannel] the message should be dispatched to. + /// + /// The id scheme for virtual channels is somewhat complicated. This is + /// necessary to ensure that there are no conflicts even when both endpoints + /// have virtual channels with the same id; since both endpoints can send and + /// receive messages across each virtual channel, a naïve scheme would make it + /// impossible to tell whether a message was from a channel that originated in + /// the remote endpoint or a reply on a channel that originated in the local + /// endpoint. + /// + /// The trick is that each endpoint only uses odd ids for its own channels. + /// When sending a message over a channel that was created by the remote + /// endpoint, the channel's id plus one is used. This way each [MultiChannel] + /// knows that if an incoming message has an odd id, it's using the local id + /// scheme, but if it has an even id, it's using the remote id scheme. + var _nextId = 1; + + _MultiChannel(this._innerStream, this._innerSink) { + // The default connection is a special case which has id 0 on both ends. + // This allows it to begin connected without having to send over an id. + _streamControllers[0] = _streamController; + _sinkControllers[0] = _sinkController; + _sinkController.stream.listen( + (message) => _innerSink.add([0, message]), + onDone: () => _closeChannel(0, 0)); + + _innerStreamSubscription = _innerStream.listen((message) { + var id = message[0]; + var sink = _streamControllers[id]; + + // A sink might not exist if the channel was closed before an incoming + // message was processed. + if (sink == null) return; + if (message.length > 1) { + sink.add(message[1]); + return; + } + + // A message without data indicates that the channel has been closed. + _sinkControllers[id].close(); + }, onDone: _closeInnerChannel, + onError: _streamController.addError); + } + + VirtualChannel virtualChannel([id]) { + if (_innerStream == null) { + throw new StateError("The underlying channel is closed."); + } + + var inputId; + var outputId; + if (id != null) { + // Since the user is passing in an id, we're connected to a remote + // VirtualChannel. This means messages they send over this channel will + // have the original odd id, but our replies will have an even id. + inputId = id; + outputId = (id as int) + 1; + } else { + // Since we're generating an id, we originated this VirtualChannel. This + // means messages we send over this channel will have the original odd id, + // but the remote channel's replies will have an even id. + inputId = _nextId + 1; + outputId = _nextId; + _nextId += 2; + } + + if (_streamControllers.containsKey(inputId)) { + throw new ArgumentError("A virtual channel with id $id already exists."); + } + + var streamController = new StreamController(sync: true); + var sinkController = new StreamController(sync: true); + _streamControllers[inputId] = streamController; + _sinkControllers[inputId] = sinkController; + sinkController.stream.listen( + (message) => _innerSink.add([outputId, message]), + onDone: () => _closeChannel(inputId, outputId)); + + return new VirtualChannel._( + this, outputId, streamController.stream, sinkController.sink); + } + + /// Closes the virtual channel for which incoming messages have [inputId] and + /// outgoing messages have [outputId]. + void _closeChannel(int inputId, int outputId) { + _streamControllers.remove(inputId).close(); + _sinkControllers.remove(inputId).close(); + + if (_innerSink == null) return; + + // A message without data indicates that the virtual channel has been + // closed. + _innerSink.add([outputId]); + if (_streamControllers.isEmpty) _closeInnerChannel(); + } + + /// Closes the underlying communication channel. + void _closeInnerChannel() { + _innerSink.close(); + _innerStreamSubscription.cancel(); + _innerStream = null; + _innerSink = null; + for (var controller in _sinkControllers.values.toList()) { + controller.close(); + } + } +} + +/// A virtual channel created by [MultiChannel]. +/// +/// This implements [MultiChannel] for convenience. +/// [VirtualChannel.virtualChannel] is semantically identical to the parent's +/// [MultiChannel.virtualChannel]. +class VirtualChannel extends StreamChannelMixin implements MultiChannel { + /// The [MultiChannel] that created this. + final MultiChannel _parent; + + /// The identifier for this channel. + /// + /// This can be sent across the [MultiChannel] to provide the remote endpoint + /// a means to connect to this channel. Nothing about this is guaranteed + /// except that it will be JSON-serializable. + final id; + + final Stream stream; + final StreamSink sink; + + VirtualChannel._(this._parent, this.id, this.stream, this.sink); + + VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart new file mode 100644 index 0000000000..c4e28a0e37 --- /dev/null +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, 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'; + +export 'src/multi_channel.dart'; + +/// An abstract class representing a two-way communication channel. +/// +/// Subclasses are strongly encouraged to mix in or extend [StreamChannelMixin] +/// to get default implementations of the various instance methods. Adding new +/// methods to this interface will not be considered a breaking change if +/// implementations are also added to [StreamChannelMixin]. +abstract class StreamChannel { + /// The stream that emits values from the other endpoint. + Stream get stream; + + /// The sink for sending values to the other endpoint. + StreamSink get sink; + + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + factory StreamChannel(Stream stream, StreamSink sink) => + new _StreamChannel(stream, sink); + + /// Connects [this] to [other], so that any values emitted by either are sent + /// directly to the other. + void pipe(StreamChannel other); +} + +/// An implementation of [StreamChannel] that simply takes a stream and a sink +/// as parameters. +/// +/// This is distinct from [StreamChannel] so that it can use +/// [StreamChannelMixin]. +class _StreamChannel extends StreamChannelMixin { + final Stream stream; + final StreamSink sink; + + _StreamChannel(this.stream, this.sink); +} + +/// A mixin that implements the instance methods of [StreamChannel] in terms of +/// [stream] and [sink]. +abstract class StreamChannelMixin implements StreamChannel { + void pipe(StreamChannel other) { + stream.pipe(other.sink); + other.stream.pipe(sink); + } +} diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart new file mode 100644 index 0000000000..e4594128a9 --- /dev/null +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -0,0 +1,310 @@ +// Copyright (c) 2016, 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:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var oneToTwo; + var twoToOne; + var channel1; + var channel2; + setUp(() { + oneToTwo = new StreamController(); + twoToOne = new StreamController(); + channel1 = new MultiChannel(twoToOne.stream, oneToTwo.sink); + channel2 = new MultiChannel(oneToTwo.stream, twoToOne.sink); + }); + + group("the default virtual channel", () { + test("begins connected", () { + var first = true; + channel2.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + channel1.sink.add("hello"); + channel1.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(channel2.stream.toList(), completion(isEmpty)); + expect(channel2.sink.done, completes); + + channel1.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(channel1.stream.toList(), completion(isEmpty)); + expect(channel1.sink.done, completes); + + channel1.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + channel1.sink.done.then(expectAsync((_) {}, count: 0)); + + channel1.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () { + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + channel1.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + // Establish another virtual connection which should keep the underlying + // connection open. + channel2.virtualChannel(channel1.virtualChannel().id); + channel1.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + }); + + group("a locally-created virtual channel", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("sends messages only to the other virtual channel", () { + var first = true; + virtual2.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + // No other virtual channels should receive the message. + for (var i = 0; i < 10; i++) { + var virtual = channel2.virtualChannel(channel1.virtualChannel().id); + virtual.stream.listen(expectAsync((_) {}, count: 0)); + } + channel2.stream.listen(expectAsync((_) {}, count: 0)); + + virtual1.sink.add("hello"); + virtual1.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + virtual1.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + + virtual1.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + virtual1.sink.done.then(expectAsync((_) {}, count: 0)); + virtual1.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () async { + // First close the default channel so we can test the new channel as the + // last living virtual channel. + channel1.sink.close(); + + await channel2.stream.toList(); + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + virtual1.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + virtual1.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + + test("doesn't conflict with a remote virtual channel", () { + var virtual3 = channel2.virtualChannel(); + var virtual4 = channel1.virtualChannel(virtual3.id); + + // This is an implementation detail, but we assert it here to make sure + // we're properly testing two channels with the same id. + expect(virtual1.id, equals(virtual3.id)); + + virtual2.stream.listen( + expectAsync((message) => expect(message, equals("hello")))); + virtual4.stream.listen( + expectAsync((message) => expect(message, equals("goodbye")))); + + virtual1.sink.add("hello"); + virtual3.sink.add("goodbye"); + }); + }); + + group("a remotely-created virtual channel", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("sends messages only to the other virtual channel", () { + var first = true; + virtual1.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + // No other virtual channels should receive the message. + for (var i = 0; i < 10; i++) { + var virtual = channel2.virtualChannel(channel1.virtualChannel().id); + virtual.stream.listen(expectAsync((_) {}, count: 0)); + } + channel1.stream.listen(expectAsync((_) {}, count: 0)); + + virtual2.sink.add("hello"); + virtual2.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + + virtual2.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + virtual2.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + virtual2.sink.done.then(expectAsync((_) {}, count: 0)); + virtual2.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () async { + // First close the default channel so we can test the new channel as the + // last living virtual channel. + channel2.sink.close(); + + await channel1.stream.toList(); + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + virtual2.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + virtual2.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + + test("doesn't allow another virtual channel with the same id", () { + expect(() => channel2.virtualChannel(virtual1.id), + throwsArgumentError); + }); + }); + + group("when the underlying stream", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("closes, all virtual channels close", () { + expect(channel1.stream.toList(), completion(isEmpty)); + expect(channel1.sink.done, completes); + expect(channel2.stream.toList(), completion(isEmpty)); + expect(channel2.sink.done, completes); + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + oneToTwo.close(); + }); + + test("closes, no more virtual channels may be created", () { + expect(channel1.sink.done.then((_) => channel1.virtualChannel()), + throwsStateError); + expect(channel2.sink.done.then((_) => channel2.virtualChannel()), + throwsStateError); + + oneToTwo.close(); + }); + + test("emits an error, the error is sent only to the default channel", () { + channel1.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((error) => expect(error, equals("oh no")))); + virtual1.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((_) {}, count: 0)); + + twoToOne.addError("oh no"); + }); + }); +} diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart new file mode 100644 index 0000000000..130a3e12bd --- /dev/null +++ b/pkgs/stream_channel/test/utils.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2016, 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'; + +/// Returns a [Future] that completes after pumping the event queue [times] +/// times. +/// +/// By default, this should pump the event queue enough times to allow any code +/// to run, as long as it's not waiting on some external event. +Future pumpEventQueue([int times=20]) { + if (times == 0) return new Future.value(); + // Use [new Future] future to allow microtask events to finish. The [new + // Future.value] constructor uses scheduleMicrotask itself and would therefore + // not wait for microtask callbacks that are scheduled after invoking this + // method. + return new Future(() => pumpEventQueue(times - 1)); +} + From 31deacaede3144d32b836a16f8a778f93f461356 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 21 Jan 2016 15:19:27 -0800 Subject: [PATCH 004/138] Add a DelegatingStreamChannel class. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1617483003 . --- .../lib/src/delegating_stream_channel.dart | 17 +++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + 2 files changed, 18 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/delegating_stream_channel.dart diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart new file mode 100644 index 0000000000..9d6ad90fdc --- /dev/null +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2016, 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. + +/// A simple delegating wrapper around [StreamChannel]. +/// +/// Subclasses can override individual methods, or use this to expose only +/// [StreamChannel] methods. +class StreamChannelView extends StreamChannelMixin { + /// The inner channel to which methods are forwarded. + final StreamChannel _inner; + + Stream get stream => _inner.stream; + StreamSink get sink => _inner.sink; + + StreamChannelView(this._inner); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index c4e28a0e37..a8c9a09034 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -4,6 +4,7 @@ import 'dart:async'; +export 'src/delegating_stream_channel.dart'; export 'src/multi_channel.dart'; /// An abstract class representing a two-way communication channel. From 9eea7761575466adb45a7c1300a3d8d9be558cbc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 21 Jan 2016 15:29:15 -0800 Subject: [PATCH 005/138] Add clearer rules for implementations. This helps implementations know how to handle corner cases, and helps users know what behavior they can rely on. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1604903006 . --- pkgs/stream_channel/lib/stream_channel.dart | 47 ++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index a8c9a09034..fd7b093273 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -9,18 +9,55 @@ export 'src/multi_channel.dart'; /// An abstract class representing a two-way communication channel. /// -/// Subclasses are strongly encouraged to mix in or extend [StreamChannelMixin] -/// to get default implementations of the various instance methods. Adding new -/// methods to this interface will not be considered a breaking change if -/// implementations are also added to [StreamChannelMixin]. +/// Users should consider the [stream] emitting a "done" event to be the +/// canonical indicator that the channel has closed. If they wish to close the +/// channel, they should close the [sink]—canceling the stream subscription is +/// not sufficient. Protocol errors may be emitted through the stream or through +/// [Sink.done], depending on their underlying cause. Note that the sink may +/// silently drop events if the channel closes before [Sink.close] is called. +/// +/// Implementations are strongly encouraged to mix in or extend +/// [StreamChannelMixin] to get default implementations of the various instance +/// methods. Adding new methods to this interface will not be considered a +/// breaking change if implementations are also added to [StreamChannelMixin]. +/// +/// Implementations must provide the following guarantees: +/// +/// * The stream is single-subscription, and must follow all the guarantees of +/// single-subscription streams. +/// +/// * Closing the sink causes the stream to close before it emits any more +/// events. +/// +/// * After the stream closes, the sink is automatically closed. If this +/// happens, sink methods should silently drop their arguments until +/// [Sink.close] is called. +/// +/// * If the stream closes before it has a listener, the sink should silently +/// drop events if possible. +/// +/// * Canceling the stream's subscription has no effect on the sink. The channel +/// must still be able to respond to the other endpoint closing the channel +/// even after the subscription has been canceled. +/// +/// * The sink *either* forwards errors to the other endpoint *or* closes as +/// soon as an error is added and forwards that error to the [Sink.done] +/// future. +/// +/// These guarantees allow users to interact uniformly with all implementations, +/// and ensure that either endpoint closing the stream produces consistent +/// behavior. abstract class StreamChannel { - /// The stream that emits values from the other endpoint. + /// The single-subscription stream that emits values from the other endpoint. Stream get stream; /// The sink for sending values to the other endpoint. StreamSink get sink; /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// Note that this stream/sink pair must provide the guarantees listed in the + /// [StreamChannel] documentation. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); From 58ce9f4560f9141a401b4b4f77fe97cb6d63f0b6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 25 Jan 2016 15:09:57 -0800 Subject: [PATCH 006/138] Fix DelegatingStreamChannel. I apparently forgot to add imports and named it the wrong thing. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1615043004 . --- .../stream_channel/lib/src/delegating_stream_channel.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart index 9d6ad90fdc..4434cf62a0 100644 --- a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -2,16 +2,20 @@ // 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 '../stream_channel.dart'; + /// A simple delegating wrapper around [StreamChannel]. /// /// Subclasses can override individual methods, or use this to expose only /// [StreamChannel] methods. -class StreamChannelView extends StreamChannelMixin { +class DelegatingStreamChannel extends StreamChannelMixin { /// The inner channel to which methods are forwarded. final StreamChannel _inner; Stream get stream => _inner.stream; StreamSink get sink => _inner.sink; - StreamChannelView(this._inner); + DelegatingStreamChannel(this._inner); } From 8c8923d24a14f1cb4103b07d96271cca957874f9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:25:07 -0800 Subject: [PATCH 007/138] Add a StreamChannelCompleter class. This is by analogy with StreamCompleter and StreamSinkCompleter in the async package, and is in fact implemented using them. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1631103002 . --- .../lib/src/stream_channel_completer.dart | 77 +++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 + .../test/stream_channel_completer_test.dart | 124 ++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/stream_channel_completer.dart create mode 100644 pkgs/stream_channel/test/stream_channel_completer_test.dart diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart new file mode 100644 index 0000000000..d15adcf94b --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2016, 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:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [channel] where the source and destination are provided later. +/// +/// The [channel] is a normal channel that can be listened to and that events +/// can be added to immediately, but until [setChannel] is called it won't emit +/// any events and all events added to it will be buffered. +class StreamChannelCompleter { + /// The completer for this channel's stream. + final _streamCompleter = new StreamCompleter(); + + /// The completer for this channel's sink. + final _sinkCompleter = new StreamSinkCompleter(); + + /// The channel for this completer. + StreamChannel get channel => _channel; + StreamChannel _channel; + + /// Whether [setChannel] has been called. + bool _set = false; + + /// Convert a `Future` to a `StreamChannel`. + /// + /// This creates a channel using a channel completer, and sets the source + /// channel to the result of the future when the future completes. + /// + /// If the future completes with an error, the returned channel's stream will + /// instead contain just that error. The sink will silently discard all + /// events. + static StreamChannel fromFuture(Future channelFuture) { + var completer = new StreamChannelCompleter(); + channelFuture.then(completer.setChannel, onError: completer.setError); + return completer.channel; + } + + StreamChannelCompleter() { + _channel = new StreamChannel( + _streamCompleter.stream, _sinkCompleter.sink); + } + + /// Set a channel as the source and destination for [channel]. + /// + /// A channel may be set at most once. + /// + /// Either [setChannel] or [setError] may be called at most once. Trying to + /// call either of them again will fail. + void setChannel(StreamChannel channel) { + if (_set) throw new StateError("The channel has already been set."); + _set = true; + + _streamCompleter.setSourceStream(channel.stream); + _sinkCompleter.setDestinationSink(channel.sink); + } + + /// Indicates that there was an error connecting the channel. + /// + /// This makes the stream emit [error] and close. It makes the sink discard + /// all its events. + /// + /// Either [setChannel] or [setError] may be called at most once. Trying to + /// call either of them again will fail. + void setError(error, [StackTrace stackTrace]) { + if (_set) throw new StateError("The channel has already been set."); + _set = true; + + _streamCompleter.setError(error, stackTrace); + _sinkCompleter.setDestinationSink(new NullStreamSink()); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index fd7b093273..4b3c659aec 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,6 +6,7 @@ import 'dart:async'; export 'src/delegating_stream_channel.dart'; export 'src/multi_channel.dart'; +export 'src/stream_channel_completer.dart'; /// An abstract class representing a two-way communication channel. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 76f22b7da5..a0d8d22004 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -5,5 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.0.0 <2.0.0' +dependencies: + async: '^1.8.0' dev_dependencies: test: '^0.12.0' diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart new file mode 100644 index 0000000000..1ee40a5ca6 --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -0,0 +1,124 @@ +// Copyright (c) 2016, 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:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var completer; + var streamController; + var sinkController; + var innerChannel; + setUp(() { + completer = new StreamChannelCompleter(); + streamController = new StreamController(); + sinkController = new StreamController(); + innerChannel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + group("when a channel is set before accessing", () { + test("forwards events through the stream", () { + completer.setChannel(innerChannel); + expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + }); + + test("forwards events through the sink", () { + completer.setChannel(innerChannel); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + + completer.channel.sink.add(1); + completer.channel.sink.add(2); + completer.channel.sink.add(3); + completer.channel.sink.close(); + }); + + test("forwards an error through the stream", () { + completer.setError("oh no"); + expect(completer.channel.stream.first, throwsA("oh no")); + }); + + test("drops sink events", () { + completer.setError("oh no"); + expect(completer.channel.sink.done, completes); + completer.channel.sink.add(1); + completer.channel.sink.addError("oh no"); + }); + }); + + group("when a channel is set after accessing", () { + test("forwards events through the stream", () async { + expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); + await pumpEventQueue(); + + completer.setChannel(innerChannel); + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + }); + + test("forwards events through the sink", () async { + completer.channel.sink.add(1); + completer.channel.sink.add(2); + completer.channel.sink.add(3); + completer.channel.sink.close(); + await pumpEventQueue(); + + completer.setChannel(innerChannel); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards an error through the stream", () async { + expect(completer.channel.stream.first, throwsA("oh no")); + await pumpEventQueue(); + + completer.setError("oh no"); + }); + + test("drops sink events", () async { + expect(completer.channel.sink.done, completes); + completer.channel.sink.add(1); + completer.channel.sink.addError("oh no"); + await pumpEventQueue(); + + completer.setError("oh no"); + }); + }); + + group("forFuture", () { + test("forwards a StreamChannel", () { + var channel = StreamChannelCompleter.fromFuture( + new Future.value(innerChannel)); + channel.sink.add(1); + channel.sink.close(); + streamController.sink.add(2); + streamController.sink.close(); + + expect(sinkController.stream.toList(), completion(equals([1]))); + expect(channel.stream.toList(), completion(equals([2]))); + }); + + test("forwards an error", () { + var channel = StreamChannelCompleter.fromFuture( + new Future.error("oh no")); + expect(channel.stream.toList(), throwsA("oh no")); + }); + }); + + test("doesn't allow the channel to be set multiple times", () { + completer.setChannel(innerChannel); + expect(() => completer.setChannel(innerChannel), throwsStateError); + expect(() => completer.setChannel(innerChannel), throwsStateError); + }); +} From 6c2fd24f90e5556c78207390ef5bb1f5289d36c8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:26:25 -0800 Subject: [PATCH 008/138] Add an IsolateChannel class. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1635873002 . --- .../lib/src/isolate_channel.dart | 146 ++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 +- .../test/isolate_channel_test.dart | 126 +++++++++++++++ 4 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/lib/src/isolate_channel.dart create mode 100644 pkgs/stream_channel/test/isolate_channel_test.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart new file mode 100644 index 0000000000..c6645438d6 --- /dev/null +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -0,0 +1,146 @@ +// Copyright (c) 2016, 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 'dart:isolate'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, +/// presumably with another isolate. +/// +/// The remote endpoint doesn't necessarily need to be running an +/// [IsolateChannel]. This can be used with any two ports, although the +/// [StreamChannel] semantics mean that this class will treat them as being +/// paired (for example, closing the [sink] will cause the [stream] to stop +/// emitting events). +/// +/// The underlying isolate ports have no notion of closing connections. This +/// means that [stream] won't close unless [sink] is closed, and that closing +/// [sink] won't cause the remote endpoint to close. Users should take care to +/// ensure that they always close the [sink] of every [IsolateChannel] they use +/// to avoid leaving dangling [ReceivePort]s. +class IsolateChannel extends StreamChannelMixin { + /// The port that produces incoming messages. + /// + /// This is wrapped in a [StreamView] to produce [stream]. + final ReceivePort _receivePort; + + /// The port that sends outgoing messages. + final SendPort _sendPort; + + Stream get stream => _stream; + final Stream _stream; + + StreamSink get sink => _sink; + _SendPortSink _sink; + + /// Creates a stream channel that receives messages from [receivePort] and + /// sends them over [sendPort]. + IsolateChannel(ReceivePort receivePort, this._sendPort) + : _receivePort = receivePort, + _stream = new StreamView(receivePort) { + _sink = new _SendPortSink(this); + } +} + +/// The sink for [IsolateChannel]. +/// +/// [SendPort] doesn't natively implement any sink API, so this adds that API as +/// a wrapper. Closing this just closes the [ReceivePort]. +class _SendPortSink implements StreamSink { + /// The channel that this sink is for. + final IsolateChannel _channel; + + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); + + /// Whether [done] has been completed. + /// + /// This is distinct from [_closed] because [done] can complete with an error + /// without the user explicitly calling [close]. + bool get _isDone => _doneCompleter.isCompleted; + + /// Whether the user has called [close]. + bool _closed = false; + + /// Whether we're currently adding a stream with [addStream]. + bool _inAddStream = false; + + _SendPortSink(this._channel); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDone) return; + + _add(data); + } + + /// A helper for [add] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. + void _add(T data) { + _channel._sendPort.send(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + + _close(error, stackTrace); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _close(); + } + + /// A helper for [close] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. It + /// also forwards [error] and [stackTrace] to [done] if they're passed. + Future _close([error, StackTrace stackTrace]) { + if (_isDone) return done; + + _channel._receivePort.close(); + + if (error != null) { + _doneCompleter.completeError(error, stackTrace); + } else { + _doneCompleter.complete(); + } + + return done; + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDone) return; + + _inAddStream = true; + var completer = new Completer.sync(); + stream.listen(_add, + onError: (error, stackTrace) { + _close(error, stackTrace); + completer.complete(); + }, + onDone: completer.complete, + cancelOnError: true); + return completer.future.then((_) { + _inAddStream = false; + }); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 4b3c659aec..ff36ec78bd 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -5,6 +5,7 @@ import 'dart:async'; export 'src/delegating_stream_channel.dart'; +export 'src/isolate_channel.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index a0d8d22004..97057abe08 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -4,7 +4,7 @@ description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' dependencies: async: '^1.8.0' dev_dependencies: diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart new file mode 100644 index 0000000000..9e4fddc954 --- /dev/null +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -0,0 +1,126 @@ +// Copyright (c) 2016, 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 'dart:isolate'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var receivePort; + var sendPort; + var channel; + setUp(() { + receivePort = new ReceivePort(); + var receivePortForSend = new ReceivePort(); + sendPort = receivePortForSend.sendPort; + channel = new IsolateChannel(receivePortForSend, receivePort.sendPort); + }); + + tearDown(() { + receivePort.close(); + channel.sink.close(); + }); + + test("the channel can send messages", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + + expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("the channel can receive messages", () { + sendPort.send(1); + sendPort.send(2); + sendPort.send(3); + + expect(channel.stream.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("events can't be added to an explicitly-closed sink", () { + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + + group("stream channel rules", () { + test("closing the sink causes the stream to close before it emits any more " + "events", () { + sendPort.send(1); + sendPort.send(2); + sendPort.send(3); + sendPort.send(4); + sendPort.send(5); + + channel.stream.listen(expectAsync((message) { + expect(message, equals(1)); + channel.sink.close(); + }, count: 1)); + }); + + test("cancelling the stream's subscription has no effect on the sink", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("the sink closes as soon as an error is added", () async { + channel.sink.addError("oh no"); + channel.sink.add(1); + expect(channel.sink.done, throwsA("oh no")); + + // Since the sink is closed, the stream should also be closed. + expect(channel.stream.isEmpty, completion(isTrue)); + + // The other end shouldn't receive the next event, since the sink was + // closed. Pump the event queue to give it a chance to. + receivePort.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("the sink closes as soon as an error is added via addStream", + () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + + // This future shouldn't get the error, because it's sent to [Sink.done]. + expect(channel.sink.addStream(controller.stream), completes); + + controller.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + await pumpEventQueue(); + expect(canceled, isTrue); + + // Even though the sink is closed, this shouldn't throw an error because + // the user didn't explicitly close it. + channel.sink.add(1); + }); + }); +} From 1a2eb425eba28db3bd20e191c6eb7a1769550bd8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:28:31 -0800 Subject: [PATCH 009/138] Add StreamChannel.transform(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//1639643002 . --- pkgs/stream_channel/lib/stream_channel.dart | 18 ++++++ .../test/stream_channel_test.dart | 58 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 pkgs/stream_channel/test/stream_channel_test.dart diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ff36ec78bd..2885e2d237 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -3,6 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; + +import 'package:async/async.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; @@ -66,6 +69,13 @@ abstract class StreamChannel { /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); + + /// Transforms [this] using [codec]. + /// + /// This returns a stream channel that encodes all input using [Codec.encoder] + /// before passing it to this channel's [sink], and decodes all output from + /// this channel's [stream] using [Codec.decoder]. + StreamChannel transform(Codec codec); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -87,4 +97,12 @@ abstract class StreamChannelMixin implements StreamChannel { stream.pipe(other.sink); other.stream.pipe(sink); } + + StreamChannel transform(Codec codec) { + var sinkTransformer = + new StreamSinkTransformer.fromStreamTransformer(codec.encoder); + return new _StreamChannel( + stream.transform(codec.decoder), + sinkTransformer.bind(sink)); + } } diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart new file mode 100644 index 0000000000..30a7db4faf --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, 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 'dart:convert'; +import 'dart:isolate'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + test("pipe() pipes data from each channel's stream into the other's sink", + () { + var otherStreamController = new StreamController(); + var otherSinkController = new StreamController(); + var otherChannel = new StreamChannel( + otherStreamController.stream, otherSinkController.sink); + channel.pipe(otherChannel); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + expect(otherSinkController.stream.toList(), completion(equals([1, 2, 3]))); + + otherStreamController.add(4); + otherStreamController.add(5); + otherStreamController.add(6); + otherStreamController.close(); + expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); + }); + + test("transform() transforms the channel", () { + var transformed = channel.transform(UTF8); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), completion(equals(["foobar"]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals([[102, 98, 108, 116, 104, 112]]))); + }); +} From 8a594ea113d24950f2d6723b8f8034cb3bd81779 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 27 Jan 2016 15:24:46 -0800 Subject: [PATCH 010/138] Add StreamChannelTransformer. This makes StreamChannel.transform() take a StreamChannelTransformer rather than a codec. This is better, since a codec is explicitly intended to convert chunked data, while transformers are more general. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1632903004 . --- .../lib/src/isolate_channel.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 52 +++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 21 +++----- .../test/stream_channel_test.dart | 3 +- 4 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/stream_channel_transformer.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c6645438d6..46375c986e 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -128,7 +128,7 @@ class _SendPortSink implements StreamSink { if (_inAddStream) { throw new StateError("Cannot add stream while adding stream."); } - if (_isDone) return; + if (_isDone) return new Future.value(); _inAddStream = true; var completer = new Completer.sync(); diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart new file mode 100644 index 0000000000..be032c60dc --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -0,0 +1,52 @@ +// Copyright (c) 2016, 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 'dart:convert'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannelTransformer] transforms the events being passed to and +/// emitted by a [StreamChannel]. +/// +/// This works on the same principle as [StreamTransformer] and +/// [StreamSinkTransformer]. Each transformer defines a [bind] method that takes +/// in the original [StreamChannel] and returns the transformed version. +/// +/// Transformers must be able to have `bind` called multiple times. +class StreamChannelTransformer { + /// The transformer to use on the channel's stream. + final StreamTransformer _streamTransformer; + + /// The transformer to use on the channel's sink. + final StreamSinkTransformer _sinkTransformer; + + /// Creates a [StreamChannelTransformer] from existing stream and sink + /// transformers. + const StreamChannelTransformer( + this._streamTransformer, this._sinkTransformer); + + /// Creates a [StreamChannelTransformer] from a codec's encoder and decoder. + /// + /// All input to the inner channel's sink is encoded using [Codec.encoder], + /// and all output from its stream is decoded using [Codec.decoder]. + StreamChannelTransformer.fromCodec(Codec codec) + : this( + codec.decoder, + new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + + /// Transforms the events sent to and emitted by [channel]. + /// + /// Creates a new channel. When events are passed to the returned channel's + /// sink, the transformer will transform them and pass the transformed + /// versions to `channel.sink`. When events are emitted from the + /// `channel.straem`, the transformer will transform them and pass the + /// transformed versions to the returned channel's stream. + StreamChannel bind(StreamChannel channel) => + new StreamChannel( + channel.stream.transform(_streamTransformer), + _sinkTransformer.bind(channel.sink)); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 2885e2d237..e7fb055aa0 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -3,14 +3,14 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:convert'; -import 'package:async/async.dart'; +import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; +export 'src/stream_channel_transformer.dart'; /// An abstract class representing a two-way communication channel. /// @@ -70,12 +70,10 @@ abstract class StreamChannel { /// directly to the other. void pipe(StreamChannel other); - /// Transforms [this] using [codec]. + /// Transforms [this] using [transformer]. /// - /// This returns a stream channel that encodes all input using [Codec.encoder] - /// before passing it to this channel's [sink], and decodes all output from - /// this channel's [stream] using [Codec.decoder]. - StreamChannel transform(Codec codec); + /// This is identical to calling `transformer.bind(channel)`. + StreamChannel transform(StreamChannelTransformer transformer); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -98,11 +96,6 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(Codec codec) { - var sinkTransformer = - new StreamSinkTransformer.fromStreamTransformer(codec.encoder); - return new _StreamChannel( - stream.transform(codec.decoder), - sinkTransformer.bind(sink)); - } + StreamChannel transform(StreamChannelTransformer transformer) => + transformer.bind(this); } diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 30a7db4faf..5f006c39c6 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -44,7 +44,8 @@ void main() { }); test("transform() transforms the channel", () { - var transformed = channel.transform(UTF8); + var transformed = channel.transform( + new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 83b986e85c009e5dfd42c11e64381ba062cf0bd4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 27 Jan 2016 15:28:46 -0800 Subject: [PATCH 011/138] Add IsolateChannel.connect* constructors. These constructors use a lightweight protocol to establish a two-way connection over a previously-one-way connection. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1638183002 . --- .../lib/src/isolate_channel.dart | 172 +++++++----------- .../src/isolate_channel/send_port_sink.dart | 111 +++++++++++ pkgs/stream_channel/pubspec.yaml | 1 + .../test/isolate_channel_test.dart | 35 ++++ 4 files changed, 208 insertions(+), 111 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 46375c986e..a466d87f3e 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -5,7 +5,11 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:async/async.dart'; +import 'package:stack_trace/stack_trace.dart'; + import '../stream_channel.dart'; +import 'isolate_channel/send_port_sink.dart'; /// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, /// presumably with another isolate. @@ -22,125 +26,71 @@ import '../stream_channel.dart'; /// ensure that they always close the [sink] of every [IsolateChannel] they use /// to avoid leaving dangling [ReceivePort]s. class IsolateChannel extends StreamChannelMixin { - /// The port that produces incoming messages. - /// - /// This is wrapped in a [StreamView] to produce [stream]. - final ReceivePort _receivePort; - - /// The port that sends outgoing messages. - final SendPort _sendPort; - - Stream get stream => _stream; - final Stream _stream; - - StreamSink get sink => _sink; - _SendPortSink _sink; + final Stream stream; + final StreamSink sink; - /// Creates a stream channel that receives messages from [receivePort] and - /// sends them over [sendPort]. - IsolateChannel(ReceivePort receivePort, this._sendPort) - : _receivePort = receivePort, - _stream = new StreamView(receivePort) { - _sink = new _SendPortSink(this); - } -} - -/// The sink for [IsolateChannel]. -/// -/// [SendPort] doesn't natively implement any sink API, so this adds that API as -/// a wrapper. Closing this just closes the [ReceivePort]. -class _SendPortSink implements StreamSink { - /// The channel that this sink is for. - final IsolateChannel _channel; - - Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); - - /// Whether [done] has been completed. + /// Connects to a remote channel that was created with + /// [IsolateChannel.connectSend]. /// - /// This is distinct from [_closed] because [done] can complete with an error - /// without the user explicitly calling [close]. - bool get _isDone => _doneCompleter.isCompleted; - - /// Whether the user has called [close]. - bool _closed = false; - - /// Whether we're currently adding a stream with [addStream]. - bool _inAddStream = false; - - _SendPortSink(this._channel); - - void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - if (_isDone) return; - - _add(data); - } - - /// A helper for [add] that doesn't check for [StateError]s. + /// These constructors establish a connection using only a single + /// [SendPort]/[ReceivePort] pair, as long as each side uses one of the + /// connect constructors. /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. - void _add(T data) { - _channel._sendPort.send(data); - } - - void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - - _close(error, stackTrace); - } - - Future close() { - if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); - } + /// The connection protocol is guaranteed to remain compatible across versions + /// at least until the next major version release. If the protocol is + /// violated, the resulting channel will emit a single value on its stream and + /// then close. + factory IsolateChannel.connectReceive(ReceivePort receivePort) { + // We can't use a [StreamChannelCompleter] here because we need the return + // value to be an [IsolateChannel]. + var streamCompleter = new StreamCompleter(); + var sinkCompleter = new StreamSinkCompleter(); + var channel = new IsolateChannel._( + streamCompleter.stream, sinkCompleter.sink); + + // The first message across the ReceivePort should be a SendPort pointing to + // the remote end. If it's not, we'll make the stream emit an error + // complaining. + var subscription; + subscription = receivePort.listen((message) { + if (message is SendPort) { + streamCompleter.setSourceStream( + new SubscriptionStream(subscription)); + sinkCompleter.setDestinationSink( + new SendPortSink(receivePort, message)); + return; + } + + streamCompleter.setError( + new StateError('Unexpected Isolate response "$message".'), + new Trace.current()); + sinkCompleter.setDestinationSink(new NullStreamSink()); + subscription.cancel(); + }); - _closed = true; - return _close(); + return channel; } - /// A helper for [close] that doesn't check for [StateError]s. + /// Connects to a remote channel that was created with + /// [IsolateChannel.connectReceive]. /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. It - /// also forwards [error] and [stackTrace] to [done] if they're passed. - Future _close([error, StackTrace stackTrace]) { - if (_isDone) return done; - - _channel._receivePort.close(); - - if (error != null) { - _doneCompleter.completeError(error, stackTrace); - } else { - _doneCompleter.complete(); - } - - return done; + /// These constructors establish a connection using only a single + /// [SendPort]/[ReceivePort] pair, as long as each side uses one of the + /// connect constructors. + /// + /// The connection protocol is guaranteed to remain compatible across versions + /// at least until the next major version release. + factory IsolateChannel.connectSend(SendPort sendPort) { + var receivePort = new ReceivePort(); + sendPort.send(receivePort.sendPort); + return new IsolateChannel(receivePort, sendPort); } - Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); - if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); - } - if (_isDone) return new Future.value(); + /// Creates a stream channel that receives messages from [receivePort] and + /// sends them over [sendPort]. + IsolateChannel(ReceivePort receivePort, SendPort sendPort) + : stream = new StreamView(receivePort), + sink = new SendPortSink(receivePort, sendPort); - _inAddStream = true; - var completer = new Completer.sync(); - stream.listen(_add, - onError: (error, stackTrace) { - _close(error, stackTrace); - completer.complete(); - }, - onDone: completer.complete, - cancelOnError: true); - return completer.future.then((_) { - _inAddStream = false; - }); - } + IsolateChannel._(this.stream, this.sink); } diff --git a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart new file mode 100644 index 0000000000..d98f1da65d --- /dev/null +++ b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart @@ -0,0 +1,111 @@ +// Copyright (c) 2016, 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 'dart:isolate'; + +/// The sink for [IsolateChannel]. +/// +/// [SendPort] doesn't natively implement any sink API, so this adds that API as +/// a wrapper. Closing this just closes the [ReceivePort]. +class SendPortSink implements StreamSink { + /// The port that produces incoming messages. + /// + /// This is wrapped in a [StreamView] to produce [stream]. + final ReceivePort _receivePort; + + /// The port that sends outgoing messages. + final SendPort _sendPort; + + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); + + /// Whether [done] has been completed. + /// + /// This is distinct from [_closed] because [done] can complete with an error + /// without the user explicitly calling [close]. + bool get _isDone => _doneCompleter.isCompleted; + + /// Whether the user has called [close]. + bool _closed = false; + + /// Whether we're currently adding a stream with [addStream]. + bool _inAddStream = false; + + SendPortSink(this._receivePort, this._sendPort); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDone) return; + + _add(data); + } + + /// A helper for [add] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. + void _add(T data) { + _sendPort.send(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + + _close(error, stackTrace); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _close(); + } + + /// A helper for [close] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. It + /// also forwards [error] and [stackTrace] to [done] if they're passed. + Future _close([error, StackTrace stackTrace]) { + if (_isDone) return done; + + _receivePort.close(); + + if (error != null) { + _doneCompleter.completeError(error, stackTrace); + } else { + _doneCompleter.complete(); + } + + return done; + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDone) return new Future.value(); + + _inAddStream = true; + var completer = new Completer.sync(); + stream.listen(_add, + onError: (error, stackTrace) { + _close(error, stackTrace); + completer.complete(); + }, + onDone: completer.complete, + cancelOnError: true); + return completer.future.then((_) { + _inAddStream = false; + }); + } +} diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 97057abe08..a8e26cd172 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,5 +7,6 @@ environment: sdk: '>=1.8.0 <2.0.0' dependencies: async: '^1.8.0' + stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.0' diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 9e4fddc954..fa4d8d5325 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -123,4 +123,39 @@ void main() { channel.sink.add(1); }); }); + + group("connect constructors", () { + var connectPort; + setUp(() { + connectPort = new ReceivePort(); + }); + + tearDown(() { + connectPort.close(); + }); + + test("create a connected pair of channels", () { + var channel1 = new IsolateChannel.connectReceive(connectPort); + var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + expect(channel2.stream.take(3).toList(), completion(equals([1, 2, 3]))); + + channel2.sink.add(4); + channel2.sink.add(5); + channel2.sink.add(6); + expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); + }); + + test("the receiving channel produces an error if it gets the wrong message", + () { + var connectedChannel = new IsolateChannel.connectReceive(connectPort); + connectPort.sendPort.send("wrong value"); + + expect(connectedChannel.stream.toList(), throwsStateError); + expect(connectedChannel.sink.done, completes); + }); + }); } From 58a473046d65f1ca07349c933a071de2df8c11a6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 12:00:25 -0800 Subject: [PATCH 012/138] Add a document-by-document JSON transformer. This makes it easy to send JSON over WebSocket connections, for example. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1643843002 . --- .../lib/src/json_document_transformer.dart | 41 +++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + .../test/json_document_transformer_test.dart | 50 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/json_document_transformer.dart create mode 100644 pkgs/stream_channel/test/json_document_transformer_test.dart diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart new file mode 100644 index 0000000000..8d8dcce231 --- /dev/null +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2016, 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:convert'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; +import 'stream_channel_transformer.dart'; + +/// The canonical instance of [JsonDocumentTransformer]. +final jsonDocument = new JsonDocumentTransformer(); + +/// A [StreamChannelTransformer] that transforms JSON documents—strings that +/// contain individual objects encoded as JSON—into decoded Dart objects. +/// +/// This decodes JSON that's emitted by the transformed channel's stream, and +/// encodes objects so that JSON is passed to the transformed channel's sink. +class JsonDocumentTransformer + implements StreamChannelTransformer { + /// The underlying codec that implements the encoding and decoding logic. + final JsonCodec _codec; + + /// Creates a new transformer. + /// + /// The [reviver] and [toEncodable] arguments work the same way as the + /// corresponding arguments to [new JsonCodec]. + JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) + : _codec = new JsonCodec(reviver: reviver, toEncodable: toEncodable); + + JsonDocumentTransformer._(this._codec); + + StreamChannel bind(StreamChannel channel) { + var stream = channel.stream.map(_codec.decode); + var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { + sink.add(_codec.encode(data)); + }).bind(channel.sink); + return new StreamChannel(stream, sink); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index e7fb055aa0..f914188e6f 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -8,6 +8,7 @@ import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; +export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; export 'src/stream_channel_transformer.dart'; diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart new file mode 100644 index 0000000000..fec3d2ac11 --- /dev/null +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, 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 'dart:convert'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + test("decodes JSON emitted by the channel", () { + var transformed = channel.transform(jsonDocument); + streamController.add('{"foo": "bar"}'); + expect(transformed.stream.first, completion(equals({"foo": "bar"}))); + }); + + test("encodes objects added to the channel", () { + var transformed = channel.transform(jsonDocument); + transformed.sink.add({"foo": "bar"}); + expect(sinkController.stream.first, + completion(equals(JSON.encode({"foo": "bar"})))); + }); + + test("supports the reviver function", () { + var transformed = channel.transform( + new JsonDocumentTransformer(reviver: (key, value) => "decoded")); + streamController.add('{"foo": "bar"}'); + expect(transformed.stream.first, completion(equals("decoded"))); + }); + + test("supports the toEncodable function", () { + var transformed = channel.transform( + new JsonDocumentTransformer(toEncodable: (object) => "encoded")); + transformed.sink.add(new Object()); + expect(sinkController.stream.first, completion(equals('"encoded"'))); + }); +} From 27f7f49ac0aa49d6934ce0d67aac7674b65909e9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 13:04:12 -0800 Subject: [PATCH 013/138] Release version 1.0.0. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1647983003 . --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 847d60daa4..31490590d5 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 1.0.0 * Initial version diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index a8e26cd172..5f1a739633 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.0-dev +version: 1.0.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From b2d21787d4dca41b75b03fd0c4ea68f8273b1cc9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 14:10:11 -0800 Subject: [PATCH 014/138] Fix the MultiChannel constructor. R=kevmoo@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//1644943004 . --- pkgs/stream_channel/CHANGELOG.md | 6 +++ .../stream_channel/lib/src/multi_channel.dart | 39 ++++++++----------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 6 ++- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 31490590d5..c85bbe3c45 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.1 + +* Fix `MultiChannel`'s constructor to take a `StreamChannel`. This is + technically a breaking change, but since 1.0.0 was only released an hour ago, + we're treating it as a bug fix. + ## 1.0.0 * Initial version diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e87deb33bc..cba592ab56 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -52,12 +52,11 @@ abstract class MultiChannel implements StreamChannel { /// virtual channels may be opened. StreamSink get sink; - /// Creates a new [MultiChannel] that sends messages over [innerStream] and - /// [innerSink]. + /// Creates a new [MultiChannel] that sends and receives messages over + /// [inner]. /// - /// The inner streams must take JSON-like objects. - factory MultiChannel(Stream innerStream, StreamSink innerSink) => - new _MultiChannel(innerStream, innerSink); + /// The inner channel must take JSON-like objects. + factory MultiChannel(StreamChannel inner) => new _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -78,17 +77,12 @@ abstract class MultiChannel implements StreamChannel { /// This is private so that [VirtualChannel] can inherit from [MultiChannel] /// without having to implement all the private members. class _MultiChannel extends StreamChannelMixin implements MultiChannel { - /// The inner stream over which all communication is received. + /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - Stream _innerStream; + StreamChannel _inner; - /// The inner sink over which all communication is sent. - /// - /// This will be `null` if the underlying communication channel is closed. - StreamSink _innerSink; - - /// The subscription to [_innerStream]. + /// The subscription to [_inner.stream]. StreamSubscription _innerStreamSubscription; Stream get stream => _streamController.stream; @@ -128,16 +122,16 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// scheme, but if it has an even id, it's using the remote id scheme. var _nextId = 1; - _MultiChannel(this._innerStream, this._innerSink) { + _MultiChannel(this._inner) { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. _streamControllers[0] = _streamController; _sinkControllers[0] = _sinkController; _sinkController.stream.listen( - (message) => _innerSink.add([0, message]), + (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _innerStream.listen((message) { + _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; var sink = _streamControllers[id]; @@ -156,7 +150,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { } VirtualChannel virtualChannel([id]) { - if (_innerStream == null) { + if (_inner == null) { throw new StateError("The underlying channel is closed."); } @@ -186,7 +180,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _streamControllers[inputId] = streamController; _sinkControllers[inputId] = sinkController; sinkController.stream.listen( - (message) => _innerSink.add([outputId, message]), + (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return new VirtualChannel._( @@ -199,20 +193,19 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _streamControllers.remove(inputId).close(); _sinkControllers.remove(inputId).close(); - if (_innerSink == null) return; + if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. - _innerSink.add([outputId]); + _inner.sink.add([outputId]); if (_streamControllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. void _closeInnerChannel() { - _innerSink.close(); + _inner.sink.close(); _innerStreamSubscription.cancel(); - _innerStream = null; - _innerSink = null; + _inner = null; for (var controller in _sinkControllers.values.toList()) { controller.close(); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5f1a739633..09df4a7973 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.0 +version: 1.0.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index e4594128a9..cc9ed1d269 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -17,8 +17,10 @@ void main() { setUp(() { oneToTwo = new StreamController(); twoToOne = new StreamController(); - channel1 = new MultiChannel(twoToOne.stream, oneToTwo.sink); - channel2 = new MultiChannel(oneToTwo.stream, twoToOne.sink); + channel1 = new MultiChannel( + new StreamChannel(twoToOne.stream, oneToTwo.sink)); + channel2 = new MultiChannel( + new StreamChannel(oneToTwo.stream, twoToOne.sink)); }); group("the default virtual channel", () { From 7c16f9368ea38930bc96099fa956cdd6d835d550 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 15:55:12 -0800 Subject: [PATCH 015/138] Be more explicit about JSON error handling. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1658833002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ .../lib/src/json_document_transformer.dart | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/json_document_transformer_test.dart | 12 ++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index c85bbe3c45..d101ea0d20 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2 + +* Be more explicit about `JsonDocumentTransformer`'s error-handling behavior. + ## 1.0.1 * Fix `MultiChannel`'s constructor to take a `StreamChannel`. This is diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 8d8dcce231..19b2e08f75 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -17,6 +17,10 @@ final jsonDocument = new JsonDocumentTransformer(); /// /// This decodes JSON that's emitted by the transformed channel's stream, and /// encodes objects so that JSON is passed to the transformed channel's sink. +/// +/// If the transformed channel emits invalid JSON, this emits a +/// [FormatException]. If an unencodable object is added to the sink, it +/// synchronously throws a [JsonUnsupportedObjectError]. class JsonDocumentTransformer implements StreamChannelTransformer { /// The underlying codec that implements the encoding and decoding logic. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 09df4a7973..54e919873e 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.1 +version: 1.0.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index fec3d2ac11..65a3497245 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -47,4 +47,16 @@ void main() { transformed.sink.add(new Object()); expect(sinkController.stream.first, completion(equals('"encoded"'))); }); + + test("emits a stream error when incoming JSON is malformed", () { + var transformed = channel.transform(jsonDocument); + streamController.add("{invalid"); + expect(transformed.stream.first, throwsFormatException); + }); + + test("synchronously throws if an unencodable object is added", () { + var transformed = channel.transform(jsonDocument); + expect(() => transformed.sink.add(new Object()), + throwsA(new isInstanceOf())); + }); } From ad406409f2380deb69e76cca692eeac9d3140470 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 15:56:24 -0800 Subject: [PATCH 016/138] Add support for stream- and sink-specific changes. These are especially useful when doing stream-specific transformations like error handling. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1657943002 . --- pkgs/stream_channel/CHANGELOG.md | 6 +- pkgs/stream_channel/lib/stream_channel.dart | 28 +++++++++ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_test.dart | 59 +++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index d101ea0d20..ab0807249b 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,8 @@ -## 1.0.2 +## 1.1.0 + +* Add `StreamChannel.transformStream()`, `StreamChannel.transformSink()`, + `StreamChannel.changeStream()`, and `StreamChannel.changeSink()` to support + changing only the stream or only the sink of a channel. * Be more explicit about `JsonDocumentTransformer`'s error-handling behavior. diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index f914188e6f..ff3104212f 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -75,6 +77,20 @@ abstract class StreamChannel { /// /// This is identical to calling `transformer.bind(channel)`. StreamChannel transform(StreamChannelTransformer transformer); + + /// Transforms only the [stream] component of [this] using [transformer]. + StreamChannel transformStream(StreamTransformer transformer); + + /// Transforms only the [sink] component of [this] using [transformer]. + StreamChannel transformSink(StreamSinkTransformer transformer); + + /// Returns a copy of [this] with [stream] replaced by [change]'s return + /// value. + StreamChannel changeStream(Stream change(Stream stream)); + + /// Returns a copy of [this] with [sink] replaced by [change]'s return + /// value. + StreamChannel changeSink(StreamSink change(StreamSink sink)); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -99,4 +115,16 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); + + StreamChannel transformStream(StreamTransformer transformer) => + changeStream(transformer.bind); + + StreamChannel transformSink(StreamSinkTransformer transformer) => + changeSink(transformer.bind); + + StreamChannel changeStream(Stream change(Stream stream)) => + new StreamChannel(change(stream), sink); + + StreamChannel changeSink(StreamSink change(StreamSink sink)) => + new StreamChannel(stream, change(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 54e919873e..7ef11010f0 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.2 +version: 1.1.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 5f006c39c6..f5251778d7 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:isolate'; +import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -56,4 +57,62 @@ void main() { expect(sinkController.stream.toList(), completion(equals([[102, 98, 108, 116, 104, 112]]))); }); + + test("transformStream() transforms only the stream", () { + var transformed = channel.transformStream(UTF8.decoder); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), completion(equals(["foobar"]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals(["fblthp"]))); + }); + + test("transformSink() transforms only the sink", () { + var transformed = channel.transformSink( + new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), + completion(equals([[102, 111, 111, 98, 97, 114]]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals([[102, 98, 108, 116, 104, 112]]))); + }); + + test("changeStream() changes the stream", () { + var newController = new StreamController(); + var changed = channel.changeStream((stream) { + expect(stream, equals(channel.stream)); + return newController.stream; + }); + + newController.add(10); + newController.close(); + + streamController.add(20); + streamController.close(); + + expect(changed.stream.toList(), completion(equals([10]))); + }); + + test("changeSink() changes the sink", () { + var newController = new StreamController(); + var changed = channel.changeSink((sink) { + expect(sink, equals(channel.sink)); + return newController.sink; + }); + + expect(newController.stream.toList(), completion(equals([10]))); + streamController.stream.listen(expectAsync((_) {}, count: 0)); + + changed.sink.add(10); + changed.sink.close(); + }); } From a251a33379742b54d2752003d37a079b457f06bd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 17:29:51 -0800 Subject: [PATCH 017/138] Fix inverted generic parameters. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1658893002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/stream_channel.dart | 4 ++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ab0807249b..8138708743 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.1 + +* Fix the type annotation for `StreamChannel.transform()`'s parameter. + ## 1.1.0 * Add `StreamChannel.transformStream()`, `StreamChannel.transformSink()`, diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ff3104212f..7fff6744cd 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -76,7 +76,7 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform(StreamChannelTransformer transformer); + StreamChannel transform(StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -113,7 +113,7 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(StreamChannelTransformer transformer) => + StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7ef11010f0..7d1c6a3e47 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.1.0 +version: 1.1.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From d0af7ea9dedf277718f7fb9272f712babcd3f73f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 3 Feb 2016 17:33:46 -0800 Subject: [PATCH 018/138] Add StreamChannel.withGuarantees and StreamChannelController. These APIs make it easier for users to create their own stream channels that follow the StreamChannel guarantees. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1662773003 . --- pkgs/stream_channel/CHANGELOG.md | 8 + .../lib/src/guarantee_channel.dart | 163 ++++++++++++++++++ .../lib/src/stream_channel_controller.dart | 58 +++++++ pkgs/stream_channel/lib/stream_channel.dart | 14 +- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_controller_test.dart | 86 +++++++++ .../test/with_guarantees_test.dart | 110 ++++++++++++ 7 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/guarantee_channel.dart create mode 100644 pkgs/stream_channel/lib/src/stream_channel_controller.dart create mode 100644 pkgs/stream_channel/test/stream_channel_controller_test.dart create mode 100644 pkgs/stream_channel/test/with_guarantees_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8138708743..0b61d81f8e 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.2.0 + +* Add `new StreamChannel.withGuarantees()`, which creates a channel with extra + wrapping to ensure that it obeys the stream channel guarantees. + +* Add `StreamChannelController`, which can be used to create custom + `StreamChannel` objects. + ## 1.1.1 * Fix the type annotation for `StreamChannel.transform()`'s parameter. diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart new file mode 100644 index 0000000000..849cc2ffe7 --- /dev/null +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -0,0 +1,163 @@ +// Copyright (c) 2016, 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:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that enforces the stream channel guarantees. +/// +/// This is exposed via [new StreamChannel.withGuarantees]. +class GuaranteeChannel extends StreamChannelMixin { + Stream get stream => _streamController.stream; + + StreamSink get sink => _sink; + _GuaranteeSink _sink; + + /// The controller for [stream]. + /// + /// This intermediate controller allows us to continue listening for a done + /// event even after the user has canceled their subscription, and to send our + /// own done event when the sink is closed. + StreamController _streamController; + + /// The subscription to the inner stream. + StreamSubscription _subscription; + + /// Whether the sink has closed, causing the underlying channel to disconnect. + bool _disconnected = false; + + GuaranteeChannel(Stream innerStream, StreamSink innerSink) { + _sink = new _GuaranteeSink(innerSink, this); + + // Enforce the single-subscription guarantee by changing a broadcast stream + // to single-subscription. + if (innerStream.isBroadcast) { + innerStream = innerStream.transform( + const SingleSubscriptionTransformer()); + } + + _streamController = new StreamController(onListen: () { + // If the sink has disconnected, we've already called + // [_streamController.close]. + if (_disconnected) return; + + _subscription = innerStream.listen(_streamController.add, + onError: _streamController.addError, + onDone: () { + _sink._onStreamDisconnected(); + _streamController.close(); + }); + }, sync: true); + } + + /// Called by [_GuaranteeSink] when the user closes it. + /// + /// The sink closing indicates that the connection is closed, so the stream + /// should stop emitting events. + void _onSinkDisconnected() { + _disconnected = true; + if (_subscription != null) _subscription.cancel(); + _streamController.close(); + } +} + +/// The sink for [GuaranteeChannel]. +/// +/// This wraps the inner sink to ignore events and cancel any in-progress +/// [addStream] calls when the underlying channel closes. +class _GuaranteeSink implements StreamSink { + /// The inner sink being wrapped. + final StreamSink _inner; + + /// The [GuaranteeChannel] this belongs to. + final GuaranteeChannel _channel; + + Future get done => _inner.done; + + /// Whether the stream has emitted a done event, causing the underlying + /// channel to disconnect. + bool _disconnected = false; + + /// Whether the user has called [close]. + bool _closed = false; + + /// The subscription to the stream passed to [addStream], if a stream is + /// currently being added. + StreamSubscription _addStreamSubscription; + + /// The completer for the future returned by [addStream], if a stream is + /// currently being added. + Completer _addStreamCompleter; + + /// Whether we're currently adding a stream with [addStream]. + bool get _inAddStream => _addStreamSubscription != null; + + _GuaranteeSink(this._inner, this._channel); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_disconnected) return; + + _inner.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_disconnected) return; + + _inner.addError(error, stackTrace); + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_disconnected) return new Future.value(); + + _addStreamCompleter = new Completer.sync(); + _addStreamSubscription = stream.listen( + _inner.add, + onError: _inner.addError, + onDone: _addStreamCompleter.complete); + return _addStreamCompleter.future.then((_) { + _addStreamCompleter = null; + _addStreamSubscription = null; + }); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + if (_disconnected) return new Future.value(); + + _channel._onSinkDisconnected(); + return _inner.close(); + } + + /// Called by [GuaranteeChannel] when the stream emits a done event. + /// + /// The stream being done indicates that the connection is closed, so the + /// sink should stop forwarding events. + void _onStreamDisconnected() { + _disconnected = true; + if (!_inAddStream) return; + + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } +} diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart new file mode 100644 index 0000000000..1812a0e3a3 --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, 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 '../stream_channel.dart'; + +/// A controller for exposing a new [StreamChannel]. +/// +/// This exposes two connected [StreamChannel]s, [local] and [foreign]. The +/// user's code should use [local] to emit and receive events. Then [foreign] +/// can be returned for others to use. For example, here's a simplified version +/// of the implementation of [new IsolateChannel]: +/// +/// ```dart +/// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { +/// var controller = new StreamChannelController(); +/// +/// // Pipe all events from the receive port into the local sink... +/// receivePort.pipe(controller.local.sink); +/// +/// // ...and all events from the local stream into the send port. +/// controller.local.listen(sendPort.add, onDone: receivePort.close); +/// +/// // Then return the foreign controller for your users to use. +/// return controller.foreign; +/// } +/// ``` +class StreamChannelController { + /// The local channel. + /// + /// This channel should be used directly by the creator of this + /// [StreamChannelController] to send and receive events. + StreamChannel get local => _local; + StreamChannel _local; + + /// The foreign channel. + /// + /// This channel should be returned to external users so they can communicate + /// with [local]. + StreamChannel get foreign => _foreign; + StreamChannel _foreign; + + /// Creates a [StreamChannelController]. + /// + /// If [sync] is true, events added to either channel's sink are synchronously + /// dispatched to the other channel's stream. This should only be done if the + /// source of those events is already asynchronous. + StreamChannelController({bool sync: false}) { + var localToForeignController = new StreamController(sync: sync); + var foreignToLocalController = new StreamController(sync: sync); + _local = new StreamChannel.withGuarantees( + foreignToLocalController.stream, localToForeignController.sink); + _foreign = new StreamChannel.withGuarantees( + localToForeignController.stream, foreignToLocalController.sink); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 7fff6744cd..8c4fad5205 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -13,6 +14,7 @@ export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; +export 'src/stream_channel_controller.dart'; export 'src/stream_channel_transformer.dart'; /// An abstract class representing a two-way communication channel. @@ -65,10 +67,20 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// /// Note that this stream/sink pair must provide the guarantees listed in the - /// [StreamChannel] documentation. + /// [StreamChannel] documentation. If they don't do so natively, [new + /// StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// Unlike [new StreamChannel], this enforces the guarantees listed in the + /// [StreamChannel] documentation. This makes it somewhat less efficient than + /// just wrapping a stream and a sink directly, so [new StreamChannel] should + /// be used when the guarantees are provided natively. + factory StreamChannel.withGuarantees(Stream stream, StreamSink sink) => + new GuaranteeChannel(stream, sink); + /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7d1c6a3e47..f0b830ca18 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.1.1 +version: 1.2.0-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart new file mode 100644 index 0000000000..e45f090624 --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2016, 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:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + group("asynchronously", () { + var controller; + setUp(() { + controller = new StreamChannelController(); + }); + + test("forwards events from the local sink to the foreign stream", () { + controller.local.sink..add(1)..add(2)..add(3)..close(); + expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards events from the foreign sink to the local stream", () { + controller.foreign.sink..add(1)..add(2)..add(3)..close(); + expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); + }); + }); + + group("synchronously", () { + var controller; + setUp(() { + controller = new StreamChannelController(sync: true); + }); + + test("synchronously forwards events from the local sink to the foreign " + "stream", () { + var receivedEvent = false; + var receivedError = false; + var receivedDone = false; + controller.foreign.stream.listen(expectAsync((event) { + expect(event, equals(1)); + receivedEvent = true; + }), onError: expectAsync((error) { + expect(error, equals("oh no")); + receivedError = true; + }), onDone: expectAsync(() { + receivedDone = true; + })); + + controller.local.sink.add(1); + expect(receivedEvent, isTrue); + + controller.local.sink.addError("oh no"); + expect(receivedError, isTrue); + + controller.local.sink.close(); + expect(receivedDone, isTrue); + }); + + test("synchronously forwards events from the foreign sink to the local " + "stream", () { + var receivedEvent = false; + var receivedError = false; + var receivedDone = false; + controller.local.stream.listen(expectAsync((event) { + expect(event, equals(1)); + receivedEvent = true; + }), onError: expectAsync((error) { + expect(error, equals("oh no")); + receivedError = true; + }), onDone: expectAsync(() { + receivedDone = true; + })); + + controller.foreign.sink.add(1); + expect(receivedEvent, isTrue); + + controller.foreign.sink.addError("oh no"); + expect(receivedError, isTrue); + + controller.foreign.sink.close(); + expect(receivedDone, isTrue); + }); + }); +} diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart new file mode 100644 index 0000000000..0e95f9d883 --- /dev/null +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2016, 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:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink); + }); + + group("with a broadcast stream", () { + setUp(() { + streamController = new StreamController.broadcast(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink); + }); + + test("buffers events", () async { + streamController.add(1); + streamController.add(2); + streamController.add(3); + await pumpEventQueue(); + + expect(channel.stream.toList(), completion(equals([1, 2, 3]))); + streamController.close(); + }); + + test("only allows a single subscription", () { + channel.stream.listen(null); + expect(() => channel.stream.listen(null), throwsStateError); + }); + }); + + test("closing the event sink causes the stream to close before it emits any " + "more events", () { + streamController.add(1); + streamController.add(2); + streamController.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)).asFuture(), completes); + }); + + test("after the stream closes, the sink ignores events", () async { + streamController.close(); + + // Wait for the done event to be delivered. + await channel.stream.toList(); + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + // None of our channel.sink additions should make it to the other endpoint. + sinkController.stream.listen( + expectAsync((_) {}, count: 0), + onDone: expectAsync(() {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + streamController.close(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + // The sink should be ignoring events because the stream closed. + sinkController.stream.listen( + expectAsync((_) {}, count: 0), + onDone: expectAsync(() {}, count: 0)); + await pumpEventQueue(); + }); + + test("forwards errors to the other endpoint", () { + channel.sink.addError("error"); + expect(sinkController.stream.first, throwsA("error")); + }); +} From 8bd8af51f53b27dd99eeac67a8b8bfa2d0548bd4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 4 Feb 2016 16:10:16 -0800 Subject: [PATCH 019/138] Provide more error-handling customization. This makes it easier to wrap underlying channels that don't support errors at all. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1669953002 . --- .../lib/src/guarantee_channel.dart | 52 +++++++++++++++---- .../lib/src/stream_channel_controller.dart | 10 +++- pkgs/stream_channel/lib/stream_channel.dart | 9 +++- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_controller_test.dart | 11 ++++ .../test/with_guarantees_test.dart | 40 ++++++++++++++ 6 files changed, 108 insertions(+), 16 deletions(-) diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 849cc2ffe7..1047e14ff2 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -30,8 +30,10 @@ class GuaranteeChannel extends StreamChannelMixin { /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; - GuaranteeChannel(Stream innerStream, StreamSink innerSink) { - _sink = new _GuaranteeSink(innerSink, this); + GuaranteeChannel(Stream innerStream, StreamSink innerSink, + {bool allowSinkErrors: true}) { + _sink = new _GuaranteeSink(innerSink, this, + allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. @@ -76,10 +78,13 @@ class _GuaranteeSink implements StreamSink { /// The [GuaranteeChannel] this belongs to. final GuaranteeChannel _channel; - Future get done => _inner.done; + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); - /// Whether the stream has emitted a done event, causing the underlying - /// channel to disconnect. + /// Whether connection is disconnected. + /// + /// This can happen because the stream has emitted a done event, or because + /// the user added an error when [_allowErrors] is `false`. bool _disconnected = false; /// Whether the user has called [close]. @@ -96,7 +101,14 @@ class _GuaranteeSink implements StreamSink { /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; - _GuaranteeSink(this._inner, this._channel); + /// Whether errors are passed on to the underlying sink. + /// + /// If this is `false`, any error passed to the sink is piped to [done] and + /// the underlying sink is closed. + final bool _allowErrors; + + _GuaranteeSink(this._inner, this._channel, {bool allowErrors: true}) + : _allowErrors = allowErrors; void add(T data) { if (_closed) throw new StateError("Cannot add event after closing."); @@ -115,7 +127,20 @@ class _GuaranteeSink implements StreamSink { } if (_disconnected) return; - _inner.addError(error, stackTrace); + if (_allowErrors) { + _inner.addError(error, stackTrace); + return; + } + + _doneCompleter.completeError(error, stackTrace); + + // Treat an error like both the stream and sink disconnecting. + _onStreamDisconnected(); + _channel._onSinkDisconnected(); + + // Ignore errors from the inner sink. We're already surfacing one error, and + // if the user handles it we don't want them to have another top-level. + _inner.close().catchError((_) {}); } Future addStream(Stream stream) { @@ -141,11 +166,15 @@ class _GuaranteeSink implements StreamSink { throw new StateError("Cannot close sink while adding stream."); } + if (_closed) return done; _closed = true; - if (_disconnected) return new Future.value(); - _channel._onSinkDisconnected(); - return _inner.close(); + if (!_disconnected) { + _channel._onSinkDisconnected(); + _doneCompleter.complete(_inner.close()); + } + + return done; } /// Called by [GuaranteeChannel] when the stream emits a done event. @@ -154,8 +183,9 @@ class _GuaranteeSink implements StreamSink { /// sink should stop forwarding events. void _onStreamDisconnected() { _disconnected = true; - if (!_inAddStream) return; + if (!_doneCompleter.isCompleted) _doneCompleter.complete(); + if (!_inAddStream) return; _addStreamCompleter.complete(_addStreamSubscription.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 1812a0e3a3..ad78323eff 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -47,12 +47,18 @@ class StreamChannelController { /// If [sync] is true, events added to either channel's sink are synchronously /// dispatched to the other channel's stream. This should only be done if the /// source of those events is already asynchronous. - StreamChannelController({bool sync: false}) { + /// + /// If [allowForeignErrors] is `false`, errors are not allowed to be passed to + /// the foreign channel's sink. If any are, the connection will close and the + /// error will be forwarded to the foreign channel's [Sink.done] future. This + /// guarantees that the local stream will never emit errors. + StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { var localToForeignController = new StreamController(sync: sync); var foreignToLocalController = new StreamController(sync: sync); _local = new StreamChannel.withGuarantees( foreignToLocalController.stream, localToForeignController.sink); _foreign = new StreamChannel.withGuarantees( - localToForeignController.stream, foreignToLocalController.sink); + localToForeignController.stream, foreignToLocalController.sink, + allowSinkErrors: allowForeignErrors); } } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 8c4fad5205..992f7026a4 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -78,8 +78,13 @@ abstract class StreamChannel { /// [StreamChannel] documentation. This makes it somewhat less efficient than /// just wrapping a stream and a sink directly, so [new StreamChannel] should /// be used when the guarantees are provided natively. - factory StreamChannel.withGuarantees(Stream stream, StreamSink sink) => - new GuaranteeChannel(stream, sink); + /// + /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to + /// [sink]. If any are, the connection will close and the error will be + /// forwarded to [Sink.done]. + factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, + {bool allowSinkErrors: true}) => + new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index f0b830ca18..52ee52171e 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.2.0-dev +version: 1.2.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index e45f090624..cf8a31b36d 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -25,6 +25,17 @@ void main() { controller.foreign.sink..add(1)..add(2)..add(3)..close(); expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); }); + + test("with allowForeignErrors: false, shuts down the connection if an " + "error is added to the foreign channel", () { + controller = new StreamChannelController(allowForeignErrors: false); + + controller.foreign.sink.addError("oh no"); + expect(controller.foreign.sink.done, throwsA("oh no")); + expect(controller.foreign.stream.toList(), completion(isEmpty)); + expect(controller.local.sink.done, completes); + expect(controller.local.stream.toList(), completion(isEmpty)); + }); }); group("synchronously", () { diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 0e95f9d883..38afefac07 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -107,4 +107,44 @@ void main() { channel.sink.addError("error"); expect(sinkController.stream.first, throwsA("error")); }); + + test("Sink.done completes once the stream is done", () { + channel.stream.listen(null); + expect(channel.sink.done, completes); + streamController.close(); + }); + + group("with allowSinkErrors: false", () { + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink, allowSinkErrors: false); + }); + + test("forwards errors to Sink.done but not the stream", () { + channel.sink.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + sinkController.stream.listen(null, + onError: expectAsync((_) {}, count: 0)); + }); + + test("adding an error causes the stream to emit a done event", () { + expect(channel.sink.done, throwsA("oh no")); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.addError("oh no"); + }, count: 2)).asFuture(), completes); + }); + + test("adding an error closes the inner sink", () { + channel.sink.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + expect(sinkController.stream.toList(), completion(isEmpty)); + }); + }); } From f5810280eba19d7de62256fc35170c3e345d9dcc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 8 Feb 2016 16:11:18 -0800 Subject: [PATCH 020/138] Make IsolateChannel use StreamChannelCompleter. This exposed some lingering bugs in GuaranteeChannel as well. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1671763002 . --- .../lib/src/guarantee_channel.dart | 10 +- .../lib/src/isolate_channel.dart | 22 ++-- .../src/isolate_channel/send_port_sink.dart | 111 ------------------ .../lib/src/stream_channel_controller.dart | 4 +- .../test/with_guarantees_test.dart | 43 +++++++ 5 files changed, 68 insertions(+), 122 deletions(-) delete mode 100644 pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 1047e14ff2..a874799c1f 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -127,6 +127,14 @@ class _GuaranteeSink implements StreamSink { } if (_disconnected) return; + _addError(error, stackTrace); + } + + /// Like [addError], but doesn't check to ensure that an error can be added. + /// + /// This is called from [addStream], so it shouldn't fail if a stream is being + /// added. + void _addError(error, [StackTrace stackTrace]) { if (_allowErrors) { _inner.addError(error, stackTrace); return; @@ -153,7 +161,7 @@ class _GuaranteeSink implements StreamSink { _addStreamCompleter = new Completer.sync(); _addStreamSubscription = stream.listen( _inner.add, - onError: _inner.addError, + onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index a466d87f3e..3466d19dd1 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -9,7 +9,6 @@ import 'package:async/async.dart'; import 'package:stack_trace/stack_trace.dart'; import '../stream_channel.dart'; -import 'isolate_channel/send_port_sink.dart'; /// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, /// presumably with another isolate. @@ -54,10 +53,13 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - streamCompleter.setSourceStream( - new SubscriptionStream(subscription)); - sinkCompleter.setDestinationSink( - new SendPortSink(receivePort, message)); + var controller = new StreamChannelController(allowForeignErrors: false); + new SubscriptionStream(subscription).pipe(controller.local.sink); + controller.local.stream.listen(message.send, + onDone: receivePort.close); + + streamCompleter.setSourceStream(controller.foreign.stream); + sinkCompleter.setDestinationSink(controller.foreign.sink); return; } @@ -88,9 +90,13 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. - IsolateChannel(ReceivePort receivePort, SendPort sendPort) - : stream = new StreamView(receivePort), - sink = new SendPortSink(receivePort, sendPort); + factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { + var controller = new StreamChannelController(allowForeignErrors: false); + receivePort.pipe(controller.local.sink); + controller.local.stream.listen(sendPort.send, onDone: receivePort.close); + return new IsolateChannel._( + controller.foreign.stream, controller.foreign.sink); + } IsolateChannel._(this.stream, this.sink); } diff --git a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart deleted file mode 100644 index d98f1da65d..0000000000 --- a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2016, 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 'dart:isolate'; - -/// The sink for [IsolateChannel]. -/// -/// [SendPort] doesn't natively implement any sink API, so this adds that API as -/// a wrapper. Closing this just closes the [ReceivePort]. -class SendPortSink implements StreamSink { - /// The port that produces incoming messages. - /// - /// This is wrapped in a [StreamView] to produce [stream]. - final ReceivePort _receivePort; - - /// The port that sends outgoing messages. - final SendPort _sendPort; - - Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); - - /// Whether [done] has been completed. - /// - /// This is distinct from [_closed] because [done] can complete with an error - /// without the user explicitly calling [close]. - bool get _isDone => _doneCompleter.isCompleted; - - /// Whether the user has called [close]. - bool _closed = false; - - /// Whether we're currently adding a stream with [addStream]. - bool _inAddStream = false; - - SendPortSink(this._receivePort, this._sendPort); - - void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - if (_isDone) return; - - _add(data); - } - - /// A helper for [add] that doesn't check for [StateError]s. - /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. - void _add(T data) { - _sendPort.send(data); - } - - void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - - _close(error, stackTrace); - } - - Future close() { - if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); - } - - _closed = true; - return _close(); - } - - /// A helper for [close] that doesn't check for [StateError]s. - /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. It - /// also forwards [error] and [stackTrace] to [done] if they're passed. - Future _close([error, StackTrace stackTrace]) { - if (_isDone) return done; - - _receivePort.close(); - - if (error != null) { - _doneCompleter.completeError(error, stackTrace); - } else { - _doneCompleter.complete(); - } - - return done; - } - - Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); - if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); - } - if (_isDone) return new Future.value(); - - _inAddStream = true; - var completer = new Completer.sync(); - stream.listen(_add, - onError: (error, stackTrace) { - _close(error, stackTrace); - completer.complete(); - }, - onDone: completer.complete, - cancelOnError: true); - return completer.future.then((_) { - _inAddStream = false; - }); - } -} diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index ad78323eff..45b2865ed3 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -15,13 +15,13 @@ import '../stream_channel.dart'; /// /// ```dart /// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { -/// var controller = new StreamChannelController(); +/// var controller = new StreamChannelController(allowForeignErrors: false); /// /// // Pipe all events from the receive port into the local sink... /// receivePort.pipe(controller.local.sink); /// /// // ...and all events from the local stream into the send port. -/// controller.local.listen(sendPort.add, onDone: receivePort.close); +/// controller.local.stream.listen(sendPort.send, onDone: receivePort.close); /// /// // Then return the foreign controller for your users to use. /// return controller.foreign; diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 38afefac07..409b28fdd1 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -114,6 +114,29 @@ void main() { streamController.close(); }); + test("events can't be added to an explicitly-closed sink", () { + sinkController.stream.listen(null); // Work around sdk#19095. + + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + group("with allowSinkErrors: false", () { setUp(() { streamController = new StreamController(); @@ -146,5 +169,25 @@ void main() { expect(channel.sink.done, throwsA("oh no")); expect(sinkController.stream.toList(), completion(isEmpty)); }); + + test("adding an error via via addStream causes the stream to emit a done " + "event", () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + + // This future shouldn't get the error, because it's sent to [Sink.done]. + expect(channel.sink.addStream(controller.stream), completes); + + controller.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + await pumpEventQueue(); + expect(canceled, isTrue); + + // Even though the sink is closed, this shouldn't throw an error because + // the user didn't explicitly close it. + channel.sink.add(1); + }); }); } From ed797d0f08bcf0c9368b2d21771adbeb8548079d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Feb 2016 11:11:06 -0800 Subject: [PATCH 021/138] Add a Disconnector class. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1679193002 . --- pkgs/stream_channel/CHANGELOG.md | 5 + pkgs/stream_channel/lib/src/disconnector.dart | 139 ++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 +- .../test/disconnector_test.dart | 113 ++++++++++++++ 5 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/lib/src/disconnector.dart create mode 100644 pkgs/stream_channel/test/disconnector_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0b61d81f8e..dd749369ef 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.3.0 + +* Add `Disconnector`, a transformer that allows the caller to disconnect the + transformed channel. + ## 1.2.0 * Add `new StreamChannel.withGuarantees()`, which creates a channel with extra diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart new file mode 100644 index 0000000000..35ecd1cc40 --- /dev/null +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -0,0 +1,139 @@ +// Copyright (c) 2016, 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 '../stream_channel.dart'; + +/// Allows the caller to force a channel to disconnect. +/// +/// When [disconnect] is called, the channel (or channels) transformed by this +/// transformer will act as though the remote end had disconnected—the stream +/// will emit a done event, and the sink will ignore future inputs. The inner +/// sink will also be closed to notify the remote end of the disconnection. +/// +/// If a channel is transformed after the [disconnect] has been called, it will +/// be disconnected immediately. +class Disconnector implements StreamChannelTransformer { + /// Whether [disconnect] has been called. + bool get isDisconnected => _isDisconnected; + var _isDisconnected = false; + + /// The sinks for transformed channels. + /// + /// Note that we assume that transformed channels provide the stream channel + /// guarantees. This allows us to only track sinks, because we know closing + /// the underlying sink will cause the stream to emit a done event. + final _sinks = <_DisconnectorSink>[]; + + /// Disconnects all channels that have been transformed. + void disconnect() { + _isDisconnected = true; + for (var sink in _sinks) { + sink._disconnect(); + } + _sinks.clear(); + } + + StreamChannel bind(StreamChannel channel) { + return channel.changeSink((innerSink) { + var sink = new _DisconnectorSink(innerSink); + + if (_isDisconnected) { + sink._disconnect(); + } else { + _sinks.add(sink); + } + + return sink; + }); + } +} + +/// A sink wrapper that can force a disconnection. +class _DisconnectorSink implements StreamSink { + /// The inner sink. + final StreamSink _inner; + + Future get done => _inner.done; + + /// Whether [Disconnector.disconnect] has been called. + var _isDisconnected = false; + + /// Whether the user has called [close]. + var _closed = false; + + /// The subscription to the stream passed to [addStream], if a stream is + /// currently being added. + StreamSubscription _addStreamSubscription; + + /// The completer for the future returned by [addStream], if a stream is + /// currently being added. + Completer _addStreamCompleter; + + /// Whether we're currently adding a stream with [addStream]. + bool get _inAddStream => _addStreamSubscription != null; + + _DisconnectorSink(this._inner); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDisconnected) return; + + _inner.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDisconnected) return; + + _inner.addError(error, stackTrace); + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDisconnected) return new Future.value(); + + _addStreamCompleter = new Completer.sync(); + _addStreamSubscription = stream.listen( + _inner.add, + onError: _inner.addError, + onDone: _addStreamCompleter.complete); + return _addStreamCompleter.future.then((_) { + _addStreamCompleter = null; + _addStreamSubscription = null; + }); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _inner.close(); + } + + /// Disconnects this sink. + /// + /// This closes the underlying sink and stops forwarding events. + void _disconnect() { + _isDisconnected = true; + _inner.close(); + + if (!_inAddStream) return; + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 992f7026a4..b89845d055 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -10,6 +10,7 @@ import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; +export 'src/disconnector.dart'; export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 52ee52171e..c787b95ea3 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.2.0 +version: 1.3.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart new file mode 100644 index 0000000000..09cdddc577 --- /dev/null +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -0,0 +1,113 @@ +// Copyright (c) 2016, 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 'dart:convert'; +import 'dart:isolate'; + +import 'package:async/async.dart'; +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var disconnector; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + disconnector = new Disconnector(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink) + .transform(disconnector); + }); + + group("before disconnection", () { + test("forwards events from the sink as normal", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards events to the stream as normal", () { + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + + expect(channel.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("events can't be added when the sink is explicitly closed", () { + sinkController.stream.listen(null); // Work around sdk#19095. + + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + }); + + test("cancels addStream when disconnected", () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + expect(channel.sink.addStream(controller.stream), completes); + disconnector.disconnect(); + + await pumpEventQueue(); + expect(canceled, isTrue); + }); + + group("after disconnection", () { + setUp(() => disconnector.disconnect()); + + test("closes the inner sink and ignores events to the outer sink", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + expect(sinkController.stream.toList(), completion(isEmpty)); + }); + + test("closes the stream", () { + expect(channel.stream.toList(), completion(isEmpty)); + }); + + test("completes done", () { + sinkController.stream.listen(null); // Work around sdk#19095. + expect(channel.sink.done, completes); + }); + + test("still emits state errors after explicit close", () { + sinkController.stream.listen(null); // Work around sdk#19095. + expect(channel.sink.close(), completes); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + }); + }); +} \ No newline at end of file From 0f4b74769c54889b9eaa430c4cb48d2ecacb6e5a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Feb 2016 13:08:55 -0800 Subject: [PATCH 022/138] Make IsolateChannel's controllers synchronous. This is slightly more efficient, and also make it easier for other packages to work around dart-lang/sdkdart-lang/stream_channel#25745. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1690473002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 6 ++++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index dd749369ef..05a83e0744 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +* Make `IsolateChannel` slightly more efficient. + ## 1.3.0 * Add `Disconnector`, a transformer that allows the caller to disconnect the diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 3466d19dd1..dcb52cbf36 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -53,7 +53,8 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController(allowForeignErrors: false); + var controller = new StreamChannelController( + allowForeignErrors: false, sync: true); new SubscriptionStream(subscription).pipe(controller.local.sink); controller.local.stream.listen(message.send, onDone: receivePort.close); @@ -91,7 +92,8 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController(allowForeignErrors: false); + var controller = new StreamChannelController( + allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); controller.local.stream.listen(sendPort.send, onDone: receivePort.close); return new IsolateChannel._( diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c787b95ea3..930f74431f 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.0 +version: 1.3.1-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 2ff097b8b67a2ba5dfceeb1ed5e6ec92a4e09de8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Feb 2016 14:26:24 -0800 Subject: [PATCH 023/138] Make MultiChannel follow the stream channel rules. It was written before the rules were fully fleshed-out, and I forgot to update it to comply. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1686263002 . --- pkgs/stream_channel/CHANGELOG.md | 2 + .../stream_channel/lib/src/multi_channel.dart | 86 ++++---- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 187 +++++++++++++++--- 4 files changed, 207 insertions(+), 70 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 05a83e0744..b1b735072a 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -2,6 +2,8 @@ * Make `IsolateChannel` slightly more efficient. +* Make `MultiChannel` follow the stream channel rules. + ## 1.3.0 * Add `Disconnector`, a transformer that allows the caller to disconnect the diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index cba592ab56..112997e57e 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import '../stream_channel.dart'; /// A class that multiplexes multiple virtual channels across a single @@ -85,21 +87,15 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The subscription to [_inner.stream]. StreamSubscription _innerStreamSubscription; - Stream get stream => _streamController.stream; - final _streamController = new StreamController(sync: true); - - StreamSink get sink => _sinkController.sink; - final _sinkController = new StreamController(sync: true); + Stream get stream => _mainController.foreign.stream; + StreamSink get sink => _mainController.foreign.sink; - /// A map from virtual channel ids to [StreamController]s that should be used - /// to write messages received from those channels. - final _streamControllers = new Map(); + /// The controller for this channel. + final _mainController = new StreamChannelController(sync: true); - /// A map from virtual channel ids to [StreamControllers]s that are used - /// to receive messages to write to those channels. - /// - /// Note that this uses the same keys as [_streamControllers]. - final _sinkControllers = new Map(); + /// A map from virtual channel ids to [StreamChannelController]s that should + /// be used to communicate over those channels. + final _controllers = {}; /// The next id to use for a local virtual channel. /// @@ -125,35 +121,34 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _MultiChannel(this._inner) { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. - _streamControllers[0] = _streamController; - _sinkControllers[0] = _sinkController; - _sinkController.stream.listen( + _controllers[0] = _mainController; + _mainController.local.stream.listen( (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; - var sink = _streamControllers[id]; + var controller = _controllers[id]; - // A sink might not exist if the channel was closed before an incoming - // message was processed. - if (sink == null) return; + // A controller might not exist if the channel was closed before an + // incoming message was processed. + if (controller == null) return; if (message.length > 1) { - sink.add(message[1]); + controller.local.sink.add(message[1]); return; } - // A message without data indicates that the channel has been closed. - _sinkControllers[id].close(); - }, onDone: _closeInnerChannel, - onError: _streamController.addError); + // A message without data indicates that the channel has been closed. We + // can only close the sink here without doing any more cleanup, because + // the sink closing will cause the stream to emit a done event which will + // trigger more cleanup. + controller.local.sink.close(); + }, + onDone: _closeInnerChannel, + onError: _mainController.local.sink.addError); } VirtualChannel virtualChannel([id]) { - if (_inner == null) { - throw new StateError("The underlying channel is closed."); - } - var inputId; var outputId; if (id != null) { @@ -171,34 +166,39 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _nextId += 2; } - if (_streamControllers.containsKey(inputId)) { + // If the inner channel has already closed, create new virtual channels in a + // closed state. + if (_inner == null) { + return new VirtualChannel._( + this, inputId, new Stream.empty(), new NullStreamSink()); + } + + if (_controllers.containsKey(inputId)) { throw new ArgumentError("A virtual channel with id $id already exists."); } - var streamController = new StreamController(sync: true); - var sinkController = new StreamController(sync: true); - _streamControllers[inputId] = streamController; - _sinkControllers[inputId] = sinkController; - sinkController.stream.listen( + var controller = new StreamChannelController(sync: true); + _controllers[inputId] = controller; + controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return new VirtualChannel._( - this, outputId, streamController.stream, sinkController.sink); + this, outputId, controller.foreign.stream, controller.foreign.sink); } /// Closes the virtual channel for which incoming messages have [inputId] and /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { - _streamControllers.remove(inputId).close(); - _sinkControllers.remove(inputId).close(); + var controller = _controllers.remove(inputId); + controller.local.sink.close(); if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. _inner.sink.add([outputId]); - if (_streamControllers.isEmpty) _closeInnerChannel(); + if (_controllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. @@ -206,9 +206,13 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _inner.sink.close(); _innerStreamSubscription.cancel(); _inner = null; - for (var controller in _sinkControllers.values.toList()) { - controller.close(); + + // Convert this to a list because the close is dispatched synchronously, and + // that could conceivably remove a controller from [_controllers]. + for (var controller in new List.from(_controllers.values)) { + controller.local.sink.close(); } + _controllers.clear(); } } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 930f74431f..c38c167f38 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.1-dev +version: 1.3.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index cc9ed1d269..5be2505357 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -10,17 +10,13 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - var oneToTwo; - var twoToOne; + var controller; var channel1; var channel2; setUp(() { - oneToTwo = new StreamController(); - twoToOne = new StreamController(); - channel1 = new MultiChannel( - new StreamChannel(twoToOne.stream, oneToTwo.sink)); - channel2 = new MultiChannel( - new StreamChannel(oneToTwo.stream, twoToOne.sink)); + controller = new StreamChannelController(); + channel1 = new MultiChannel(controller.local); + channel2 = new MultiChannel(controller.foreign); }); group("the default virtual channel", () { @@ -66,16 +62,16 @@ void main() { test("closes the underlying channel when it closes without any other " "virtual channels", () { - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); channel1.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); // Establish another virtual connection which should keep the underlying // connection open. @@ -149,16 +145,16 @@ void main() { channel1.sink.close(); await channel2.stream.toList(); - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); virtual1.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); virtual1.sink.close(); @@ -246,16 +242,16 @@ void main() { channel2.sink.close(); await channel1.stream.toList(); - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); virtual2.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); virtual2.sink.close(); @@ -288,16 +284,24 @@ void main() { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); - oneToTwo.close(); + controller.local.sink.close(); }); - test("closes, no more virtual channels may be created", () { - expect(channel1.sink.done.then((_) => channel1.virtualChannel()), - throwsStateError); - expect(channel2.sink.done.then((_) => channel2.virtualChannel()), - throwsStateError); + test("closes, more virtual channels are created closed", () async { + channel2.sink.close(); + virtual2.sink.close(); + + // Wait for the existing channels to emit done events. + await channel1.stream.toList(); + await virtual1.stream.toList(); + + var virtual = channel1.virtualChannel(); + expect(virtual.stream.toList(), completion(isEmpty)); + expect(virtual.sink.done, completes); - oneToTwo.close(); + virtual = channel1.virtualChannel(); + expect(virtual.stream.toList(), completion(isEmpty)); + expect(virtual.sink.done, completes); }); test("emits an error, the error is sent only to the default channel", () { @@ -306,7 +310,134 @@ void main() { virtual1.stream.listen(expectAsync((_) {}, count: 0), onError: expectAsync((_) {}, count: 0)); - twoToOne.addError("oh no"); + controller.foreign.sink.addError("oh no"); + }); + }); + + group("stream channel rules", () { + group("for the main stream:", () { + test("closing the sink causes the stream to close before it emits any more " + "events", () { + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + + channel2.stream.listen(expectAsync((message) { + expect(message, equals(1)); + channel2.sink.close(); + }, count: 1)); + }); + + test("after the stream closes, the sink ignores events", () async { + channel1.sink.close(); + + // Wait for the done event to be delivered. + await channel2.stream.toList(); + channel2.sink.add(1); + channel2.sink.add(2); + channel2.sink.add(3); + channel2.sink.close(); + + // None of our channel.sink additions should make it to the other endpoint. + channel1.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + channel1.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + channel1.sink.close(); + expect(channel2.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + channel1.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel2.sink.close(); + await pumpEventQueue(); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + channel1.sink.close(); + + // The sink should be ignoring events because the channel closed. + channel2.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + }); + + group("for a virtual channel:", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("closing the sink causes the stream to close before it emits any more " + "events", () { + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + + virtual2.stream.listen(expectAsync((message) { + expect(message, equals(1)); + virtual2.sink.close(); + }, count: 1)); + }); + + test("after the stream closes, the sink ignores events", () async { + virtual1.sink.close(); + + // Wait for the done event to be delivered. + await virtual2.stream.toList(); + virtual2.sink.add(1); + virtual2.sink.add(2); + virtual2.sink.add(3); + virtual2.sink.close(); + + // None of our virtual.sink additions should make it to the other endpoint. + virtual1.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + virtual1.stream.listen(null).cancel(); + await pumpEventQueue(); + + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + virtual1.sink.close(); + expect(virtual2.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + virtual1.stream.listen(null).cancel(); + await pumpEventQueue(); + + virtual2.sink.close(); + await pumpEventQueue(); + + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + virtual1.sink.close(); + + // The sink should be ignoring events because the stream closed. + virtual2.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); }); }); } From 05da8f92b2e7ec573bbcc55974d1c6c58f863a79 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 8 Mar 2016 17:09:46 -0800 Subject: [PATCH 024/138] Fix unused imports --- pkgs/stream_channel/test/disconnector_test.dart | 5 +---- pkgs/stream_channel/test/json_document_transformer_test.dart | 2 -- pkgs/stream_channel/test/multi_channel_test.dart | 2 -- pkgs/stream_channel/test/stream_channel_controller_test.dart | 4 ---- pkgs/stream_channel/test/stream_channel_test.dart | 3 --- 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 09cdddc577..d7fa885cda 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -3,10 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:convert'; -import 'dart:isolate'; -import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -110,4 +107,4 @@ void main() { expect(() => channel.sink.addError("oh no"), throwsStateError); }); }); -} \ No newline at end of file +} diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 65a3497245..4dd5ea7fb8 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -8,8 +8,6 @@ import 'dart:convert'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 5be2505357..0e58d382e6 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -2,8 +2,6 @@ // 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:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index cf8a31b36d..7503387d55 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -2,13 +2,9 @@ // 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:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { group("asynchronously", () { var controller; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index f5251778d7..2a6566ac7c 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -4,14 +4,11 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:isolate'; import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; From d58d636733c810835851ace1aee70c23dd4f6ef5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 14:54:50 -0700 Subject: [PATCH 025/138] Fix all strong-mode errors and warnings. R=sigmund@google.com Review URL: https://codereview.chromium.org//1966893002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/disconnector.dart | 2 +- pkgs/stream_channel/lib/src/isolate_channel.dart | 15 +++++++++------ .../lib/src/json_document_transformer.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 9 +++++---- pkgs/stream_channel/pubspec.yaml | 2 +- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index b1b735072a..a5a7e466bc 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.2 + +* Fix all strong-mode errors and warnings. + ## 1.3.1 * Make `IsolateChannel` slightly more efficient. diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 35ecd1cc40..beff71dd0e 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,7 +38,7 @@ class Disconnector implements StreamChannelTransformer { StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { - var sink = new _DisconnectorSink(innerSink); + var sink = new _DisconnectorSink(innerSink); if (_isDisconnected) { sink._disconnect(); diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index dcb52cbf36..c725fef8ee 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -44,7 +44,7 @@ class IsolateChannel extends StreamChannelMixin { // value to be an [IsolateChannel]. var streamCompleter = new StreamCompleter(); var sinkCompleter = new StreamSinkCompleter(); - var channel = new IsolateChannel._( + var channel = new IsolateChannel._( streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to @@ -53,10 +53,11 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController( + var controller = new StreamChannelController( allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription).pipe(controller.local.sink); - controller.local.stream.listen(message.send, + new SubscriptionStream(subscription).pipe(controller.local.sink); + controller.local.stream.listen( + (data) => message.send(data), onDone: receivePort.close); streamCompleter.setSourceStream(controller.foreign.stream); @@ -92,10 +93,12 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController( + var controller = new StreamChannelController( allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); - controller.local.stream.listen(sendPort.send, onDone: receivePort.close); + controller.local.stream.listen( + (data) => sendPort.send(data), + onDone: receivePort.close); return new IsolateChannel._( controller.foreign.stream, controller.foreign.sink); } diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 19b2e08f75..c62c597cb5 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -22,7 +22,7 @@ final jsonDocument = new JsonDocumentTransformer(); /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. class JsonDocumentTransformer - implements StreamChannelTransformer { + implements StreamChannelTransformer { /// The underlying codec that implements the encoding and decoding logic. final JsonCodec _codec; diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index be032c60dc..ac980859da 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -19,10 +19,10 @@ import '../stream_channel.dart'; /// Transformers must be able to have `bind` called multiple times. class StreamChannelTransformer { /// The transformer to use on the channel's stream. - final StreamTransformer _streamTransformer; + final StreamTransformer _streamTransformer; /// The transformer to use on the channel's sink. - final StreamSinkTransformer _sinkTransformer; + final StreamSinkTransformer _sinkTransformer; /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. @@ -35,8 +35,9 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this( - codec.decoder, - new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + typedStreamTransformer(codec.decoder), + StreamSinkTransformer.typed( + new StreamSinkTransformer.fromStreamTransformer(codec.encoder))); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c38c167f38..8410e05c36 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -6,7 +6,7 @@ homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.8.0 <2.0.0' dependencies: - async: '^1.8.0' + async: '^1.11.0' stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.0' From cafec58f341bd7b7cae073e9c6b7c20d3acd0ed5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 14:59:00 -0700 Subject: [PATCH 026/138] Bump the version to 1.3.2. This was supposed to happen in the last CL, but didn't instead. R=sigmund@google.com Review URL: https://codereview.chromium.org//1971573002 . --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 8410e05c36..3e87e2bba3 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.1 +version: 1.3.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 0029c282a14810946eb2e686e0792912b0127322 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 15:42:17 -0700 Subject: [PATCH 027/138] Add type-coercion functions. These match (and are based on) the coercion functions in dart-lang/async. R=sigmund@google.com Review URL: https://codereview.chromium.org//1966853003 . --- pkgs/stream_channel/.analysis_options | 2 ++ pkgs/stream_channel/CHANGELOG.md | 8 ++++++++ .../lib/src/stream_channel_transformer.dart | 16 ++++++++++++++++ .../lib/src/transformer/typed.dart | 17 +++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 10 ++++++++++ pkgs/stream_channel/pubspec.yaml | 2 +- 6 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/.analysis_options create mode 100644 pkgs/stream_channel/lib/src/transformer/typed.dart diff --git a/pkgs/stream_channel/.analysis_options b/pkgs/stream_channel/.analysis_options new file mode 100644 index 0000000000..a10d4c5a05 --- /dev/null +++ b/pkgs/stream_channel/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a5a7e466bc..6d86e48866 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.0 + +* Add `StreamChannel.cast()`, which soundly coerces the generic type of a + channel. + +* Add `StreamChannelTransformer.typed()`, which soundly coerces the generic type + of a transformer. + ## 1.3.2 * Fix all strong-mode errors and warnings. diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index ac980859da..ca09ea16be 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; +import 'transformer/typed.dart'; /// A [StreamChannelTransformer] transforms the events being passed to and /// emitted by a [StreamChannel]. @@ -24,6 +25,21 @@ class StreamChannelTransformer { /// The transformer to use on the channel's sink. final StreamSinkTransformer _sinkTransformer; + /// Creates a wrapper that coerces the type of [transformer]. + /// + /// This soundly converts a [StreamChannelTransformer] to a + /// `StreamChannelTransformer`, regardless of its original generic type, + /// by asserting that the events emitted by the transformed channel's stream + /// are instances of `T` whenever they're provided. If they're not, the stream + /// throws a [CastError]. This also means that calls to [StreamSink.add] on + /// the transformed channel's sink may throw a [CastError] if the argument + /// type doesn't match the reified type of the sink. + static StreamChannelTransformer/**/ typed/**/( + StreamChannelTransformer transformer) => + transformer is StreamChannelTransformer/**/ + ? transformer + : new TypeSafeStreamChannelTransformer(transformer); + /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. const StreamChannelTransformer( diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart new file mode 100644 index 0000000000..f35e01c985 --- /dev/null +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2016, 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 '../../stream_channel.dart'; + +/// A wrapper that coerces the generic type of the channel returned by an inner +/// transformer to `S`. +class TypeSafeStreamChannelTransformer + implements StreamChannelTransformer { + final StreamChannelTransformer _inner; + + TypeSafeStreamChannelTransformer(this._inner); + + StreamChannel bind(StreamChannel channel) => + _inner.bind(channel).cast(); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index b89845d055..3615d21295 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -109,6 +109,13 @@ abstract class StreamChannel { /// Returns a copy of [this] with [sink] replaced by [change]'s return /// value. StreamChannel changeSink(StreamSink change(StreamSink sink)); + + /// Returns a copy of [this] with the generic type coerced to [S]. + /// + /// If any events emitted by [stream] aren't of type [S], they're converted + /// into [CastError] events. Similarly, if any events are added to [sync] that + /// aren't of type [S], a [CastError] is thrown. + StreamChannel/**/ cast/**/(); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -145,4 +152,7 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel changeSink(StreamSink change(StreamSink sink)) => new StreamChannel(stream, change(sink)); + + StreamChannel/**/ cast/**/() => new StreamChannel( + DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 3e87e2bba3..1c1df31366 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.2 +version: 1.4.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 29a1b0242ec1a713d2f2957049574cf26a7c0196 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:25:39 -0700 Subject: [PATCH 028/138] Add StreamChannel.withCloseGuarantee. This also properly enforces the close guarantee for transformers provided by this package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//2041983003 . --- pkgs/stream_channel/CHANGELOG.md | 11 +++ .../lib/src/close_guarantee_channel.dart | 86 +++++++++++++++++++ .../lib/src/json_document_transformer.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 11 ++- pkgs/stream_channel/lib/stream_channel.dart | 18 +++- .../test/with_close_guarantee_test.dart | 66 ++++++++++++++ 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/close_guarantee_channel.dart create mode 100644 pkgs/stream_channel/test/with_close_guarantee_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 6d86e48866..6e3a6ac94b 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,14 @@ +## 1.5.0 + +* Add `new StreamChannel.withCloseGuarantee()` to provide the specific guarantee + that closing the sink causes the stream to close before it emits any more + events. This is the only guarantee that isn't automatically preserved when + transforming a channel. + +* `StreamChannelTransformer`s provided by the `stream_channel` package now + properly provide the guarantee that closing the sink causes the stream to + close before it emits any more events + ## 1.4.0 * Add `StreamChannel.cast()`, which soundly coerces the generic type of a diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart new file mode 100644 index 0000000000..a2c69bcb8b --- /dev/null +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2016, 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:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that specifically enforces the stream channel guarantee +/// that closing the sink causes the stream to close before it emits any more +/// events +/// +/// This is exposed via [new StreamChannel.withCloseGuarantee]. +class CloseGuaranteeChannel extends StreamChannelMixin { + Stream get stream => _stream; + _CloseGuaranteeStream _stream; + + StreamSink get sink => _sink; + _CloseGuaranteeSink _sink; + + /// The subscription to the inner stream. + StreamSubscription _subscription; + + /// Whether the sink has closed, causing the underlying channel to disconnect. + bool _disconnected = false; + + CloseGuaranteeChannel(Stream innerStream, StreamSink innerSink) { + _sink = new _CloseGuaranteeSink(innerSink, this); + _stream = new _CloseGuaranteeStream(innerStream, this); + } +} + +/// The stream for [CloseGuaranteeChannel]. +/// +/// This wraps the inner stream to save the subscription on the channel when +/// [listen] is called. +class _CloseGuaranteeStream extends Stream { + /// The inner stream this is delegating to. + final Stream _inner; + + /// The [CloseGuaranteeChannel] this belongs to. + final CloseGuaranteeChannel _channel; + + _CloseGuaranteeStream(this._inner, this._channel); + + StreamSubscription listen(void onData(T event), + {Function onError, void onDone(), bool cancelOnError}) { + // If the channel is already disconnected, we shouldn't dispatch anything + // but a done event. + if (_channel._disconnected) { + onData = null; + onError = null; + } + + var subscription = _inner.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + if (!_channel._disconnected) { + _channel._subscription = subscription; + } + return subscription; + } +} + +/// The sink for [CloseGuaranteeChannel]. +/// +/// This wraps the inner sink to cancel the stream subscription when the sink is +/// canceled. +class _CloseGuaranteeSink extends DelegatingStreamSink { + /// The [CloseGuaranteeChannel] this belongs to. + final CloseGuaranteeChannel _channel; + + _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + + Future close() { + var done = super.close(); + _channel._disconnected = true; + if (_channel._subscription != null) { + // Don't dispatch anything but a done event. + _channel._subscription.onData(null); + _channel._subscription.onError(null); + } + return done; + } +} diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index c62c597cb5..86b9ae71c3 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -40,6 +40,6 @@ class JsonDocumentTransformer var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); - return new StreamChannel(stream, sink); + return new StreamChannel.withCloseGuarantee(stream, sink); } } diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index ca09ea16be..46232d74cc 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -17,7 +17,14 @@ import 'transformer/typed.dart'; /// [StreamSinkTransformer]. Each transformer defines a [bind] method that takes /// in the original [StreamChannel] and returns the transformed version. /// -/// Transformers must be able to have `bind` called multiple times. +/// Transformers must be able to have [bind] called multiple times. If a +/// subclass implements [bind] explicitly, it should be sure that the returned +/// stream follows the second stream channel guarantee: closing the sink causes +/// the stream to close before it emits any more events. This guarantee is +/// invalidated when an asynchronous gap is added between the original stream's +/// event dispatch and the returned stream's, for example by transforming it +/// with a [StreamTransformer]. The guarantee can be easily preserved using [new +/// StreamChannel.withCloseGuarantee]. class StreamChannelTransformer { /// The transformer to use on the channel's stream. final StreamTransformer _streamTransformer; @@ -63,7 +70,7 @@ class StreamChannelTransformer { /// `channel.straem`, the transformer will transform them and pass the /// transformed versions to the returned channel's stream. StreamChannel bind(StreamChannel channel) => - new StreamChannel( + new StreamChannel.withCloseGuarantee( channel.stream.transform(_streamTransformer), _sinkTransformer.bind(channel.sink)); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 3615d21295..16323b169c 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'package:async/async.dart'; import 'src/guarantee_channel.dart'; +import 'src/close_guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -87,6 +88,19 @@ abstract class StreamChannel { {bool allowSinkErrors: true}) => new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// This specifically enforces the second guarantee: closing the sink causes + /// the stream to close before it emits any more events. This guarantee is + /// invalidated when an asynchronous gap is added between the original + /// stream's event dispatch and the returned stream's, for example by + /// transforming it with a [StreamTransformer]. This is a lighter-weight way + /// of preserving that guarantee in particular than + /// [StreamChannel.withGuarantees]. + factory StreamChannel.withCloseGuarantee(Stream stream, + StreamSink sink) => + new CloseGuaranteeChannel(stream, sink); + /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); @@ -148,10 +162,10 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); StreamChannel changeStream(Stream change(Stream stream)) => - new StreamChannel(change(stream), sink); + new StreamChannel.withCloseGuarantee(change(stream), sink); StreamChannel changeSink(StreamSink change(StreamSink sink)) => - new StreamChannel(stream, change(sink)); + new StreamChannel.withCloseGuarantee(stream, change(sink)); StreamChannel/**/ cast/**/() => new StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart new file mode 100644 index 0000000000..caf48cf1cd --- /dev/null +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -0,0 +1,66 @@ +// Copyright (c) 2016, 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:async/async.dart'; +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final _delayTransformer = new StreamTransformer.fromHandlers( + handleData: (data, sink) => new Future.microtask(() => sink.add(data)), + handleDone: (sink) => new Future.microtask(() => sink.close())); + +final _delaySinkTransformer = + new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); + +void main() { + var controller; + var channel; + setUp(() { + controller = new StreamChannelController(); + + // Add a bunch of layers of asynchronous dispatch between the channel and + // the underlying controllers. + var stream = controller.foreign.stream; + var sink = controller.foreign.sink; + for (var i = 0; i < 10; i++) { + stream = stream.transform(_delayTransformer); + sink = _delaySinkTransformer.bind(sink); + } + + channel = new StreamChannel.withCloseGuarantee(stream, sink); + }); + + test("closing the event sink causes the stream to close before it emits any " + "more events", () async { + controller.local.sink.add(1); + controller.local.sink.add(2); + controller.local.sink.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)).asFuture(), completes); + + await pumpEventQueue(); + }); + + test("closing the event sink before events are emitted causes the stream to " + "close immediately", () async { + channel.sink.close(); + channel.stream.listen( + expectAsync((_) {}, count: 0), + onError: expectAsync((_, __) {}, count: 0), + onDone: expectAsync(() {})); + + controller.local.sink.add(1); + controller.local.sink.add(2); + controller.local.sink.add(3); + controller.local.sink.close(); + + await pumpEventQueue(); + }); +} From e39e092305561edffc588391472e4bdc94df9d76 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:35:00 -0700 Subject: [PATCH 029/138] Bump the pubspec version to 1.5.0. R=cbracken@google.com Review URL: https://codereview.chromium.org//2041813003 . --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 1c1df31366..3428dac280 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.4.0 +version: 1.5.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From a35416e22a7b83ab32268f1122bc51dc148b79fa Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:54:35 -0700 Subject: [PATCH 030/138] Fix transformer tests. These tests should never have passed, since they were closing a sink before its controller emitted events. R=cbracken@google.com Review URL: https://codereview.chromium.org//2048473002 . --- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/stream_channel_test.dart | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 3428dac280..bcdfe8e785 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.5.0 +version: 1.5.1-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 2a6566ac7c..41f4c32ec3 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,13 +41,13 @@ void main() { expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); }); - test("transform() transforms the channel", () { + test("transform() transforms the channel", () async { var transformed = channel.transform( new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), completion(equals(["foobar"]))); + expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); transformed.sink.close(); @@ -55,12 +55,12 @@ void main() { completion(equals([[102, 98, 108, 116, 104, 112]]))); }); - test("transformStream() transforms only the stream", () { + test("transformStream() transforms only the stream", () async { var transformed = channel.transformStream(UTF8.decoder); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), completion(equals(["foobar"]))); + expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); transformed.sink.close(); @@ -68,14 +68,14 @@ void main() { completion(equals(["fblthp"]))); }); - test("transformSink() transforms only the sink", () { + test("transformSink() transforms only the sink", () async { var transformed = channel.transformSink( new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), - completion(equals([[102, 111, 111, 98, 97, 114]]))); + expect(await transformed.stream.toList(), + equals([[102, 111, 111, 98, 97, 114]])); transformed.sink.add("fblthp"); transformed.sink.close(); From 6a99277c40fa77a3bc7dbcc6e003d5386b0b8143 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 19 Jan 2017 13:43:02 -0800 Subject: [PATCH 031/138] Return a future from Disconnector.disconnect(). (dart-lang/stream_channel#4) --- pkgs/stream_channel/CHANGELOG.md | 5 +++ pkgs/stream_channel/lib/src/disconnector.dart | 44 ++++++++++++------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/disconnector_test.dart | 44 ++++++++++++++++++- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 6e3a6ac94b..a018418ef9 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.0 + +* `Disconnector.disconnect()` now returns a future that completes when all the + inner `StreamSink.close()` futures have completed. + ## 1.5.0 * Add `new StreamChannel.withCloseGuarantee()` to provide the specific guarantee diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index beff71dd0e..b23813e96c 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import '../stream_channel.dart'; /// Allows the caller to force a channel to disconnect. @@ -17,8 +19,7 @@ import '../stream_channel.dart'; /// be disconnected immediately. class Disconnector implements StreamChannelTransformer { /// Whether [disconnect] has been called. - bool get isDisconnected => _isDisconnected; - var _isDisconnected = false; + bool get isDisconnected => _disconnectMemo.hasRun; /// The sinks for transformed channels. /// @@ -28,20 +29,25 @@ class Disconnector implements StreamChannelTransformer { final _sinks = <_DisconnectorSink>[]; /// Disconnects all channels that have been transformed. - void disconnect() { - _isDisconnected = true; - for (var sink in _sinks) { - sink._disconnect(); - } + /// + /// Returns a future that completes when all inner sinks' [StreamSink.close] + /// futures have completed. Note that a [StreamController]'s sink won't close + /// until the corresponding stream has a listener. + Future disconnect() => _disconnectMemo.runOnce(() { + var futures = _sinks.map((sink) => sink._disconnect()).toList(); _sinks.clear(); - } + return Future.wait(futures, eagerError: true); + }); + final _disconnectMemo = new AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { var sink = new _DisconnectorSink(innerSink); - if (_isDisconnected) { - sink._disconnect(); + if (isDisconnected) { + // Ignore errors here, because otherwise there would be no way for the + // user to handle them gracefully. + sink._disconnect().catchError((_) {}); } else { _sinks.add(sink); } @@ -126,14 +132,18 @@ class _DisconnectorSink implements StreamSink { /// Disconnects this sink. /// - /// This closes the underlying sink and stops forwarding events. - void _disconnect() { + /// This closes the underlying sink and stops forwarding events. It returns + /// the [StreamSink.close] future for the underlying sink. + Future _disconnect() { _isDisconnected = true; - _inner.close(); + var future = _inner.close(); + + if (_inAddStream) { + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } - if (!_inAddStream) return; - _addStreamCompleter.complete(_addStreamSubscription.cancel()); - _addStreamCompleter = null; - _addStreamSubscription = null; + return future; } } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bcdfe8e785..46d77617c7 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.5.1-dev +version: 1.6.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index d7fa885cda..311a41c9a5 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -78,8 +79,35 @@ void main() { expect(canceled, isTrue); }); + test("disconnect() returns the close future from the inner sink", () async { + var streamController = new StreamController(); + var sinkController = new StreamController(); + var disconnector = new Disconnector(); + var sink = new _CloseCompleterSink(sinkController.sink); + var channel = new StreamChannel.withGuarantees( + streamController.stream, sink) + .transform(disconnector); + + var disconnectFutureFired = false; + expect(disconnector.disconnect().then((_) { + disconnectFutureFired = true; + }), completes); + + // Give the future time to fire early if it's going to. + await pumpEventQueue(); + expect(disconnectFutureFired, isFalse); + + // When the inner sink's close future completes, so should the + // disconnector's. + sink.completer.complete(); + await pumpEventQueue(); + expect(disconnectFutureFired, isTrue); + }); + group("after disconnection", () { - setUp(() => disconnector.disconnect()); + setUp(() { + disconnector.disconnect(); + }); test("closes the inner sink and ignores events to the outer sink", () { channel.sink.add(1); @@ -108,3 +136,17 @@ void main() { }); }); } + +/// A [StreamSink] wrapper that adds the ability to manually complete the Future +/// returned by [close] using [completer]. +class _CloseCompleterSink extends DelegatingStreamSink { + /// The completer for the future returned by [close]. + final completer = new Completer(); + + _CloseCompleterSink(StreamSink inner) : super(inner); + + Future close() { + super.close(); + return completer.future; + } +} From 963bab00ef228ba381f4fbfba1d62be09a00ff8f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 25 Jan 2017 15:01:46 -0800 Subject: [PATCH 032/138] Fix the type args for StreamChannel.transform(). (dart-lang/stream_channel#7) Closes dart-lang/stream_channel#6 --- pkgs/stream_channel/CHANGELOG.md | 6 ++++++ pkgs/stream_channel/lib/stream_channel.dart | 6 ++++-- pkgs/stream_channel/pubspec.yaml | 2 +- .../stream_channel/test/json_document_transformer_test.dart | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a018418ef9..8d44b214a7 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.1 + +* Fix the type of `StreamChannel.transform()`. This previously inverted the + generic parameters, so it only really worked with transformers where both + generic types were identical. + ## 1.6.0 * `Disconnector.disconnect()` now returns a future that completes when all the diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 16323b169c..34be085ea8 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -108,7 +108,8 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform(StreamChannelTransformer transformer); + StreamChannel/**/ transform/**/( + StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -152,7 +153,8 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(StreamChannelTransformer transformer) => + StreamChannel/**/ transform/**/( + StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 46d77617c7..7d395a3ea8 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.0 +version: 1.6.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 4dd5ea7fb8..6f18e361fb 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -11,11 +11,11 @@ import 'package:test/test.dart'; void main() { var streamController; var sinkController; - var channel; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( + channel = new StreamChannel( streamController.stream, sinkController.sink); }); From 48080d014f179add2150a1e82f78e85708cf29f5 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Wed, 26 Jul 2017 14:54:07 -0700 Subject: [PATCH 033/138] Update comment style generic syntax BUG= R=kevmoo@google.com Review-Url: https://codereview.chromium.org//2987963002 . --- .../lib/src/stream_channel_transformer.dart | 4 ++-- pkgs/stream_channel/lib/stream_channel.dart | 12 ++++++------ pkgs/stream_channel/pubspec.yaml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 46232d74cc..d6d10ff5ef 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -41,9 +41,9 @@ class StreamChannelTransformer { /// throws a [CastError]. This also means that calls to [StreamSink.add] on /// the transformed channel's sink may throw a [CastError] if the argument /// type doesn't match the reified type of the sink. - static StreamChannelTransformer/**/ typed/**/( + static StreamChannelTransformer typed( StreamChannelTransformer transformer) => - transformer is StreamChannelTransformer/**/ + transformer is StreamChannelTransformer ? transformer : new TypeSafeStreamChannelTransformer(transformer); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 34be085ea8..dcbc9a07e7 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -108,8 +108,8 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel/**/ transform/**/( - StreamChannelTransformer transformer); + StreamChannel transform( + StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -130,7 +130,7 @@ abstract class StreamChannel { /// If any events emitted by [stream] aren't of type [S], they're converted /// into [CastError] events. Similarly, if any events are added to [sync] that /// aren't of type [S], a [CastError] is thrown. - StreamChannel/**/ cast/**/(); + StreamChannel cast(); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -153,8 +153,8 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel/**/ transform/**/( - StreamChannelTransformer transformer) => + StreamChannel transform( + StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => @@ -169,6 +169,6 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel changeSink(StreamSink change(StreamSink sink)) => new StreamChannel.withCloseGuarantee(stream, change(sink)); - StreamChannel/**/ cast/**/() => new StreamChannel( + StreamChannel cast() => new StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7d395a3ea8..19a3bd07c0 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,10 @@ name: stream_channel -version: 1.6.1 +version: 1.6.2-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.21.0 <2.0.0-dev.infinity' dependencies: async: '^1.11.0' stack_trace: '^1.0.0' From 6f2269b5438c1460e5b4e71b787f2ceebf795491 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:35:03 -0700 Subject: [PATCH 034/138] Rename analysis options --- pkgs/stream_channel/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/stream_channel/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/stream_channel/.analysis_options b/pkgs/stream_channel/analysis_options.yaml similarity index 100% rename from pkgs/stream_channel/.analysis_options rename to pkgs/stream_channel/analysis_options.yaml From 398407eeaeba3fc852123300b6f65c3215a9b3bf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:37:58 -0700 Subject: [PATCH 035/138] dartfmt --- pkgs/stream_channel/lib/src/disconnector.dart | 14 +++--- .../lib/src/guarantee_channel.dart | 31 +++++++------ .../lib/src/isolate_channel.dart | 18 ++++---- .../lib/src/stream_channel_completer.dart | 4 +- .../lib/src/stream_channel_transformer.dart | 7 +-- .../lib/src/transformer/typed.dart | 2 +- pkgs/stream_channel/lib/stream_channel.dart | 10 ++--- .../test/disconnector_test.dart | 18 ++++---- .../test/isolate_channel_test.dart | 3 +- .../test/json_document_transformer_test.dart | 4 +- .../test/multi_channel_test.dart | 44 ++++++++++++------- .../test/stream_channel_completer_test.dart | 12 ++--- .../test/stream_channel_controller_test.dart | 21 ++++++--- .../test/stream_channel_test.dart | 31 ++++++++----- pkgs/stream_channel/test/utils.dart | 3 +- .../test/with_close_guarantee_test.dart | 22 ++++++---- .../test/with_guarantees_test.dart | 39 +++++++++------- 17 files changed, 160 insertions(+), 123 deletions(-) diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index b23813e96c..37a376c312 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -34,10 +34,10 @@ class Disconnector implements StreamChannelTransformer { /// futures have completed. Note that a [StreamController]'s sink won't close /// until the corresponding stream has a listener. Future disconnect() => _disconnectMemo.runOnce(() { - var futures = _sinks.map((sink) => sink._disconnect()).toList(); - _sinks.clear(); - return Future.wait(futures, eagerError: true); - }); + var futures = _sinks.map((sink) => sink._disconnect()).toList(); + _sinks.clear(); + return Future.wait(futures, eagerError: true); + }); final _disconnectMemo = new AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { @@ -111,10 +111,8 @@ class _DisconnectorSink implements StreamSink { if (_isDisconnected) return new Future.value(); _addStreamCompleter = new Completer.sync(); - _addStreamSubscription = stream.listen( - _inner.add, - onError: _inner.addError, - onDone: _addStreamCompleter.complete); + _addStreamSubscription = stream.listen(_inner.add, + onError: _inner.addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index a874799c1f..f18cbb9733 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -32,28 +32,29 @@ class GuaranteeChannel extends StreamChannelMixin { GuaranteeChannel(Stream innerStream, StreamSink innerSink, {bool allowSinkErrors: true}) { - _sink = new _GuaranteeSink(innerSink, this, - allowErrors: allowSinkErrors); + _sink = + new _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. if (innerStream.isBroadcast) { - innerStream = innerStream.transform( - const SingleSubscriptionTransformer()); + innerStream = + innerStream.transform(const SingleSubscriptionTransformer()); } - _streamController = new StreamController(onListen: () { - // If the sink has disconnected, we've already called - // [_streamController.close]. - if (_disconnected) return; + _streamController = new StreamController( + onListen: () { + // If the sink has disconnected, we've already called + // [_streamController.close]. + if (_disconnected) return; - _subscription = innerStream.listen(_streamController.add, - onError: _streamController.addError, - onDone: () { + _subscription = innerStream.listen(_streamController.add, + onError: _streamController.addError, onDone: () { _sink._onStreamDisconnected(); _streamController.close(); }); - }, sync: true); + }, + sync: true); } /// Called by [_GuaranteeSink] when the user closes it. @@ -159,10 +160,8 @@ class _GuaranteeSink implements StreamSink { if (_disconnected) return new Future.value(); _addStreamCompleter = new Completer.sync(); - _addStreamSubscription = stream.listen( - _inner.add, - onError: _addError, - onDone: _addStreamCompleter.complete); + _addStreamSubscription = stream.listen(_inner.add, + onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c725fef8ee..f1328c03d1 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -44,8 +44,8 @@ class IsolateChannel extends StreamChannelMixin { // value to be an [IsolateChannel]. var streamCompleter = new StreamCompleter(); var sinkCompleter = new StreamSinkCompleter(); - var channel = new IsolateChannel._( - streamCompleter.stream, sinkCompleter.sink); + var channel = + new IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error @@ -56,9 +56,8 @@ class IsolateChannel extends StreamChannelMixin { var controller = new StreamChannelController( allowForeignErrors: false, sync: true); new SubscriptionStream(subscription).pipe(controller.local.sink); - controller.local.stream.listen( - (data) => message.send(data), - onDone: receivePort.close); + controller.local.stream + .listen((data) => message.send(data), onDone: receivePort.close); streamCompleter.setSourceStream(controller.foreign.stream); sinkCompleter.setDestinationSink(controller.foreign.sink); @@ -93,12 +92,11 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController( - allowForeignErrors: false, sync: true); + var controller = + new StreamChannelController(allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); - controller.local.stream.listen( - (data) => sendPort.send(data), - onDone: receivePort.close); + controller.local.stream + .listen((data) => sendPort.send(data), onDone: receivePort.close); return new IsolateChannel._( controller.foreign.stream, controller.foreign.sink); } diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index d15adcf94b..b9881b9131 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -42,8 +42,8 @@ class StreamChannelCompleter { } StreamChannelCompleter() { - _channel = new StreamChannel( - _streamCompleter.stream, _sinkCompleter.sink); + _channel = + new StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); } /// Set a channel as the source and destination for [channel]. diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index d6d10ff5ef..1a4afcae2b 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -58,9 +58,10 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this( - typedStreamTransformer(codec.decoder), - StreamSinkTransformer.typed( - new StreamSinkTransformer.fromStreamTransformer(codec.encoder))); + typedStreamTransformer(codec.decoder), + StreamSinkTransformer.typed( + new StreamSinkTransformer.fromStreamTransformer( + codec.encoder))); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart index f35e01c985..9c2d72b41c 100644 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -8,7 +8,7 @@ import '../../stream_channel.dart'; /// transformer to `S`. class TypeSafeStreamChannelTransformer implements StreamChannelTransformer { - final StreamChannelTransformer _inner; + final StreamChannelTransformer _inner; TypeSafeStreamChannelTransformer(this._inner); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index dcbc9a07e7..8d0e60421f 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -97,8 +97,8 @@ abstract class StreamChannel { /// transforming it with a [StreamTransformer]. This is a lighter-weight way /// of preserving that guarantee in particular than /// [StreamChannel.withGuarantees]. - factory StreamChannel.withCloseGuarantee(Stream stream, - StreamSink sink) => + factory StreamChannel.withCloseGuarantee( + Stream stream, StreamSink sink) => new CloseGuaranteeChannel(stream, sink); /// Connects [this] to [other], so that any values emitted by either are sent @@ -108,8 +108,7 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform( - StreamChannelTransformer transformer); + StreamChannel transform(StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -153,8 +152,7 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform( - StreamChannelTransformer transformer) => + StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 311a41c9a5..e194ee3cff 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -84,14 +84,16 @@ void main() { var sinkController = new StreamController(); var disconnector = new Disconnector(); var sink = new _CloseCompleterSink(sinkController.sink); - var channel = new StreamChannel.withGuarantees( - streamController.stream, sink) - .transform(disconnector); + var channel = + new StreamChannel.withGuarantees(streamController.stream, sink) + .transform(disconnector); var disconnectFutureFired = false; - expect(disconnector.disconnect().then((_) { - disconnectFutureFired = true; - }), completes); + expect( + disconnector.disconnect().then((_) { + disconnectFutureFired = true; + }), + completes); // Give the future time to fire early if it's going to. await pumpEventQueue(); @@ -114,7 +116,7 @@ void main() { channel.sink.add(2); channel.sink.add(3); channel.sink.close(); - + expect(sinkController.stream.toList(), completion(isEmpty)); }); @@ -126,7 +128,7 @@ void main() { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.done, completes); }); - + test("still emits state errors after explicit close", () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.close(), completes); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index fa4d8d5325..7316c6a427 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -64,7 +64,8 @@ void main() { }); group("stream channel rules", () { - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { sendPort.send(1); sendPort.send(2); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 6f18e361fb..22bb830093 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -15,8 +15,8 @@ void main() { setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( - streamController.stream, sinkController.sink); + channel = + new StreamChannel(streamController.stream, sinkController.sink); }); test("decodes JSON emitted by the channel", () { diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0e58d382e6..69059b6820 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -47,7 +47,8 @@ void main() { channel1.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { channel1.sink.done.then(expectAsync((_) {}, count: 0)); @@ -58,7 +59,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () { expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); @@ -66,7 +68,8 @@ void main() { channel1.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -126,7 +129,8 @@ void main() { virtual1.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { virtual1.sink.done.then(expectAsync((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); @@ -136,7 +140,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. @@ -149,7 +154,8 @@ void main() { virtual1.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -169,10 +175,10 @@ void main() { // we're properly testing two channels with the same id. expect(virtual1.id, equals(virtual3.id)); - virtual2.stream.listen( - expectAsync((message) => expect(message, equals("hello")))); - virtual4.stream.listen( - expectAsync((message) => expect(message, equals("goodbye")))); + virtual2.stream + .listen(expectAsync((message) => expect(message, equals("hello")))); + virtual4.stream + .listen(expectAsync((message) => expect(message, equals("goodbye")))); virtual1.sink.add("hello"); virtual3.sink.add("goodbye"); @@ -223,7 +229,8 @@ void main() { virtual2.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { virtual2.sink.done.then(expectAsync((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); @@ -233,7 +240,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. @@ -246,7 +254,8 @@ void main() { virtual2.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -259,8 +268,7 @@ void main() { }); test("doesn't allow another virtual channel with the same id", () { - expect(() => channel2.virtualChannel(virtual1.id), - throwsArgumentError); + expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); }); @@ -314,7 +322,8 @@ void main() { group("stream channel rules", () { group("for the main stream:", () { - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { channel1.sink.add(1); channel1.sink.add(2); @@ -380,7 +389,8 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { virtual1.sink.add(1); virtual1.sink.add(2); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 1ee40a5ca6..e08dd8a7ac 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -18,8 +18,8 @@ void main() { completer = new StreamChannelCompleter(); streamController = new StreamController(); sinkController = new StreamController(); - innerChannel = new StreamChannel( - streamController.stream, sinkController.sink); + innerChannel = + new StreamChannel(streamController.stream, sinkController.sink); }); group("when a channel is set before accessing", () { @@ -98,8 +98,8 @@ void main() { group("forFuture", () { test("forwards a StreamChannel", () { - var channel = StreamChannelCompleter.fromFuture( - new Future.value(innerChannel)); + var channel = + StreamChannelCompleter.fromFuture(new Future.value(innerChannel)); channel.sink.add(1); channel.sink.close(); streamController.sink.add(2); @@ -110,8 +110,8 @@ void main() { }); test("forwards an error", () { - var channel = StreamChannelCompleter.fromFuture( - new Future.error("oh no")); + var channel = + StreamChannelCompleter.fromFuture(new Future.error("oh no")); expect(channel.stream.toList(), throwsA("oh no")); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 7503387d55..8162a1746e 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -13,16 +13,25 @@ void main() { }); test("forwards events from the local sink to the foreign stream", () { - controller.local.sink..add(1)..add(2)..add(3)..close(); + controller.local.sink + ..add(1) + ..add(2) + ..add(3) + ..close(); expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); }); test("forwards events from the foreign sink to the local stream", () { - controller.foreign.sink..add(1)..add(2)..add(3)..close(); + controller.foreign.sink + ..add(1) + ..add(2) + ..add(3) + ..close(); expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); }); - test("with allowForeignErrors: false, shuts down the connection if an " + test( + "with allowForeignErrors: false, shuts down the connection if an " "error is added to the foreign channel", () { controller = new StreamChannelController(allowForeignErrors: false); @@ -40,7 +49,8 @@ void main() { controller = new StreamChannelController(sync: true); }); - test("synchronously forwards events from the local sink to the foreign " + test( + "synchronously forwards events from the local sink to the foreign " "stream", () { var receivedEvent = false; var receivedError = false; @@ -65,7 +75,8 @@ void main() { expect(receivedDone, isTrue); }); - test("synchronously forwards events from the foreign sink to the local " + test( + "synchronously forwards events from the foreign sink to the local " "stream", () { var receivedEvent = false; var receivedError = false; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 41f4c32ec3..f0a8383857 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -16,8 +16,7 @@ void main() { setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( - streamController.stream, sinkController.sink); + channel = new StreamChannel(streamController.stream, sinkController.sink); }); test("pipe() pipes data from each channel's stream into the other's sink", @@ -42,8 +41,8 @@ void main() { }); test("transform() transforms the channel", () async { - var transformed = channel.transform( - new StreamChannelTransformer.fromCodec(UTF8)); + var transformed = + channel.transform(new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); @@ -51,8 +50,11 @@ void main() { transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals([[102, 98, 108, 116, 104, 112]]))); + expect( + sinkController.stream.toList(), + completion(equals([ + [102, 98, 108, 116, 104, 112] + ]))); }); test("transformStream() transforms only the stream", () async { @@ -64,8 +66,7 @@ void main() { transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals(["fblthp"]))); + expect(sinkController.stream.toList(), completion(equals(["fblthp"]))); }); test("transformSink() transforms only the sink", () async { @@ -74,13 +75,19 @@ void main() { streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(await transformed.stream.toList(), - equals([[102, 111, 111, 98, 97, 114]])); + expect( + await transformed.stream.toList(), + equals([ + [102, 111, 111, 98, 97, 114] + ])); transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals([[102, 98, 108, 116, 104, 112]]))); + expect( + sinkController.stream.toList(), + completion(equals([ + [102, 98, 108, 116, 104, 112] + ]))); }); test("changeStream() changes the stream", () { diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart index 130a3e12bd..e533895401 100644 --- a/pkgs/stream_channel/test/utils.dart +++ b/pkgs/stream_channel/test/utils.dart @@ -9,7 +9,7 @@ import 'dart:async'; /// /// By default, this should pump the event queue enough times to allow any code /// to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times=20]) { +Future pumpEventQueue([int times = 20]) { if (times == 0) return new Future.value(); // Use [new Future] future to allow microtask events to finish. The [new // Future.value] constructor uses scheduleMicrotask itself and would therefore @@ -17,4 +17,3 @@ Future pumpEventQueue([int times=20]) { // method. return new Future(() => pumpEventQueue(times - 1)); } - diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index caf48cf1cd..dafbfeffb3 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -35,26 +35,30 @@ void main() { channel = new StreamChannel.withCloseGuarantee(stream, sink); }); - test("closing the event sink causes the stream to close before it emits any " + test( + "closing the event sink causes the stream to close before it emits any " "more events", () async { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.close(); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)) + .asFuture(), + completes); await pumpEventQueue(); }); - test("closing the event sink before events are emitted causes the stream to " + test( + "closing the event sink before events are emitted causes the stream to " "close immediately", () async { channel.sink.close(); - channel.stream.listen( - expectAsync((_) {}, count: 0), - onError: expectAsync((_, __) {}, count: 0), - onDone: expectAsync(() {})); + channel.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((_, __) {}, count: 0), onDone: expectAsync(() {})); controller.local.sink.add(1); controller.local.sink.add(2); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 409b28fdd1..b8156f20a1 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -43,15 +43,20 @@ void main() { }); }); - test("closing the event sink causes the stream to close before it emits any " + test( + "closing the event sink causes the stream to close before it emits any " "more events", () { streamController.add(1); streamController.add(2); streamController.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.close(); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)) + .asFuture(), + completes); }); test("after the stream closes, the sink ignores events", () async { @@ -65,8 +70,7 @@ void main() { channel.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - sinkController.stream.listen( - expectAsync((_) {}, count: 0), + sinkController.stream.listen(expectAsync((_) {}, count: 0), onDone: expectAsync(() {}, count: 0)); await pumpEventQueue(); }); @@ -97,8 +101,7 @@ void main() { channel.sink.close(); // The sink should be ignoring events because the stream closed. - sinkController.stream.listen( - expectAsync((_) {}, count: 0), + sinkController.stream.listen(expectAsync((_) {}, count: 0), onDone: expectAsync(() {}, count: 0)); await pumpEventQueue(); }); @@ -142,14 +145,15 @@ void main() { streamController = new StreamController(); sinkController = new StreamController(); channel = new StreamChannel.withGuarantees( - streamController.stream, sinkController.sink, allowSinkErrors: false); + streamController.stream, sinkController.sink, + allowSinkErrors: false); }); test("forwards errors to Sink.done but not the stream", () { channel.sink.addError("oh no"); expect(channel.sink.done, throwsA("oh no")); - sinkController.stream.listen(null, - onError: expectAsync((_) {}, count: 0)); + sinkController.stream + .listen(null, onError: expectAsync((_) {}, count: 0)); }); test("adding an error causes the stream to emit a done event", () { @@ -159,9 +163,13 @@ void main() { streamController.add(2); streamController.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.addError("oh no"); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.addError("oh no"); + }, count: 2)) + .asFuture(), + completes); }); test("adding an error closes the inner sink", () { @@ -170,7 +178,8 @@ void main() { expect(sinkController.stream.toList(), completion(isEmpty)); }); - test("adding an error via via addStream causes the stream to emit a done " + test( + "adding an error via via addStream causes the stream to emit a done " "event", () async { var canceled = false; var controller = new StreamController(onCancel: () { From 045a8c6f5e1b02ab696c5d80e03e2013d9a06257 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:40:50 -0700 Subject: [PATCH 036/138] Stop using deprecated pkg/test expect methods --- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/isolate_channel_test.dart | 4 +- .../test/multi_channel_test.dart | 58 +++++++++---------- .../test/stream_channel_controller_test.dart | 12 ++-- .../test/stream_channel_test.dart | 2 +- .../test/with_close_guarantee_test.dart | 7 ++- .../test/with_guarantees_test.dart | 14 ++--- 7 files changed, 50 insertions(+), 49 deletions(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 19a3bd07c0..5813c4a0e2 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -9,4 +9,4 @@ dependencies: async: '^1.11.0' stack_trace: '^1.0.0' dev_dependencies: - test: '^0.12.0' + test: '^0.12.18' diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 7316c6a427..b3b252e6eb 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -73,7 +73,7 @@ void main() { sendPort.send(4); sendPort.send(5); - channel.stream.listen(expectAsync((message) { + channel.stream.listen(expectAsync1((message) { expect(message, equals(1)); channel.sink.close(); }, count: 1)); @@ -100,7 +100,7 @@ void main() { // The other end shouldn't receive the next event, since the sink was // closed. Pump the event queue to give it a chance to. - receivePort.listen(expectAsync((_) {}, count: 0)); + receivePort.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 69059b6820..b1156738a7 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -20,7 +20,7 @@ void main() { group("the default virtual channel", () { test("begins connected", () { var first = true; - channel2.stream.listen(expectAsync((message) { + channel2.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -50,7 +50,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - channel1.sink.done.then(expectAsync((_) {}, count: 0)); + channel1.sink.done.then(expectAsync1((_) {}, count: 0)); channel1.stream.listen((_) {}).cancel(); @@ -71,8 +71,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); // Establish another virtual connection which should keep the underlying // connection open. @@ -95,7 +95,7 @@ void main() { test("sends messages only to the other virtual channel", () { var first = true; - virtual2.stream.listen(expectAsync((message) { + virtual2.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -107,9 +107,9 @@ void main() { // No other virtual channels should receive the message. for (var i = 0; i < 10; i++) { var virtual = channel2.virtualChannel(channel1.virtualChannel().id); - virtual.stream.listen(expectAsync((_) {}, count: 0)); + virtual.stream.listen(expectAsync1((_) {}, count: 0)); } - channel2.stream.listen(expectAsync((_) {}, count: 0)); + channel2.stream.listen(expectAsync1((_) {}, count: 0)); virtual1.sink.add("hello"); virtual1.sink.add("world"); @@ -132,7 +132,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - virtual1.sink.done.then(expectAsync((_) {}, count: 0)); + virtual1.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); // Ensure that there's enough time for the channel to close if it's going @@ -157,8 +157,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.sink.close(); @@ -176,9 +176,9 @@ void main() { expect(virtual1.id, equals(virtual3.id)); virtual2.stream - .listen(expectAsync((message) => expect(message, equals("hello")))); - virtual4.stream - .listen(expectAsync((message) => expect(message, equals("goodbye")))); + .listen(expectAsync1((message) => expect(message, equals("hello")))); + virtual4.stream.listen( + expectAsync1((message) => expect(message, equals("goodbye")))); virtual1.sink.add("hello"); virtual3.sink.add("goodbye"); @@ -195,7 +195,7 @@ void main() { test("sends messages only to the other virtual channel", () { var first = true; - virtual1.stream.listen(expectAsync((message) { + virtual1.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -207,9 +207,9 @@ void main() { // No other virtual channels should receive the message. for (var i = 0; i < 10; i++) { var virtual = channel2.virtualChannel(channel1.virtualChannel().id); - virtual.stream.listen(expectAsync((_) {}, count: 0)); + virtual.stream.listen(expectAsync1((_) {}, count: 0)); } - channel1.stream.listen(expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0)); virtual2.sink.add("hello"); virtual2.sink.add("world"); @@ -232,7 +232,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - virtual2.sink.done.then(expectAsync((_) {}, count: 0)); + virtual2.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); // Ensure that there's enough time for the channel to close if it's going @@ -257,8 +257,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.sink.close(); @@ -311,10 +311,10 @@ void main() { }); test("emits an error, the error is sent only to the default channel", () { - channel1.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((error) => expect(error, equals("oh no")))); - virtual1.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync1((error) => expect(error, equals("oh no")))); + virtual1.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync1((_) {}, count: 0)); controller.foreign.sink.addError("oh no"); }); @@ -329,7 +329,7 @@ void main() { channel1.sink.add(2); channel1.sink.add(3); - channel2.stream.listen(expectAsync((message) { + channel2.stream.listen(expectAsync1((message) { expect(message, equals(1)); channel2.sink.close(); }, count: 1)); @@ -346,7 +346,7 @@ void main() { channel2.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - channel1.stream.listen(expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -376,7 +376,7 @@ void main() { channel1.sink.close(); // The sink should be ignoring events because the channel closed. - channel2.stream.listen(expectAsync((_) {}, count: 0)); + channel2.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); }); @@ -396,7 +396,7 @@ void main() { virtual1.sink.add(2); virtual1.sink.add(3); - virtual2.stream.listen(expectAsync((message) { + virtual2.stream.listen(expectAsync1((message) { expect(message, equals(1)); virtual2.sink.close(); }, count: 1)); @@ -413,7 +413,7 @@ void main() { virtual2.sink.close(); // None of our virtual.sink additions should make it to the other endpoint. - virtual1.stream.listen(expectAsync((_) {}, count: 0)); + virtual1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -443,7 +443,7 @@ void main() { virtual1.sink.close(); // The sink should be ignoring events because the stream closed. - virtual2.stream.listen(expectAsync((_) {}, count: 0)); + virtual2.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 8162a1746e..c092570f58 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -55,13 +55,13 @@ void main() { var receivedEvent = false; var receivedError = false; var receivedDone = false; - controller.foreign.stream.listen(expectAsync((event) { + controller.foreign.stream.listen(expectAsync1((event) { expect(event, equals(1)); receivedEvent = true; - }), onError: expectAsync((error) { + }), onError: expectAsync1((error) { expect(error, equals("oh no")); receivedError = true; - }), onDone: expectAsync(() { + }), onDone: expectAsync0(() { receivedDone = true; })); @@ -81,13 +81,13 @@ void main() { var receivedEvent = false; var receivedError = false; var receivedDone = false; - controller.local.stream.listen(expectAsync((event) { + controller.local.stream.listen(expectAsync1((event) { expect(event, equals(1)); receivedEvent = true; - }), onError: expectAsync((error) { + }), onError: expectAsync1((error) { expect(error, equals("oh no")); receivedError = true; - }), onDone: expectAsync(() { + }), onDone: expectAsync0(() { receivedDone = true; })); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index f0a8383857..b8ebcbd854 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -114,7 +114,7 @@ void main() { }); expect(newController.stream.toList(), completion(equals([10]))); - streamController.stream.listen(expectAsync((_) {}, count: 0)); + streamController.stream.listen(expectAsync1((_) {}, count: 0)); changed.sink.add(10); changed.sink.close(); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index dafbfeffb3..bed6f0db6c 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -44,7 +44,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) .asFuture(), @@ -57,8 +57,9 @@ void main() { "closing the event sink before events are emitted causes the stream to " "close immediately", () async { channel.sink.close(); - channel.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((_, __) {}, count: 0), onDone: expectAsync(() {})); + channel.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync2((_, __) {}, count: 0), + onDone: expectAsync0(() {})); controller.local.sink.add(1); controller.local.sink.add(2); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index b8156f20a1..07dd8e52f2 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -52,7 +52,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) .asFuture(), @@ -70,8 +70,8 @@ void main() { channel.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - sinkController.stream.listen(expectAsync((_) {}, count: 0), - onDone: expectAsync(() {}, count: 0)); + sinkController.stream.listen(expectAsync1((_) {}, count: 0), + onDone: expectAsync0(() {}, count: 0)); await pumpEventQueue(); }); @@ -101,8 +101,8 @@ void main() { channel.sink.close(); // The sink should be ignoring events because the stream closed. - sinkController.stream.listen(expectAsync((_) {}, count: 0), - onDone: expectAsync(() {}, count: 0)); + sinkController.stream.listen(expectAsync1((_) {}, count: 0), + onDone: expectAsync0(() {}, count: 0)); await pumpEventQueue(); }); @@ -153,7 +153,7 @@ void main() { channel.sink.addError("oh no"); expect(channel.sink.done, throwsA("oh no")); sinkController.stream - .listen(null, onError: expectAsync((_) {}, count: 0)); + .listen(null, onError: expectAsync1((_) {}, count: 0)); }); test("adding an error causes the stream to emit a done event", () { @@ -165,7 +165,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.addError("oh no"); }, count: 2)) .asFuture(), From d63ae51d3157c7cb1fe7480d04cdc54cde2a813e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:41:31 -0700 Subject: [PATCH 037/138] Remove unused var --- pkgs/stream_channel/test/disconnector_test.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index e194ee3cff..cd1300c665 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -84,9 +84,8 @@ void main() { var sinkController = new StreamController(); var disconnector = new Disconnector(); var sink = new _CloseCompleterSink(sinkController.sink); - var channel = - new StreamChannel.withGuarantees(streamController.stream, sink) - .transform(disconnector); + new StreamChannel.withGuarantees(streamController.stream, sink) + .transform(disconnector); var disconnectFutureFired = false; expect( From 97446793a44967a0257a1a5356ab33e8e7c2672e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:43:24 -0700 Subject: [PATCH 038/138] enable travis-ci --- pkgs/stream_channel/.travis.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pkgs/stream_channel/.travis.yml diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml new file mode 100644 index 0000000000..d5c64e9dde --- /dev/null +++ b/pkgs/stream_channel/.travis.yml @@ -0,0 +1,20 @@ +language: dart +sudo: false +dart: + - dev + - stable +dart_task: + - test: --platform vm + - test: --platform firefox -j 1 + - test: --platform dartium + install_dartium: true + - dartfmt + - dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From 2a9b499e0759a514025163f7819db32e58b35773 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Sep 2017 18:12:56 -0700 Subject: [PATCH 039/138] Remove -dev.infinity in SDK upper constraint --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5813c4a0e2..2d863620be 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -4,7 +4,7 @@ description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.21.0 <2.0.0-dev.infinity' + sdk: '>=1.21.0 <2.0.0' dependencies: async: '^1.11.0' stack_trace: '^1.0.0' From 6cac0360526f12590c1320f762448bdfa6c1bc99 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 22 Sep 2017 13:44:15 -0700 Subject: [PATCH 040/138] Declare support for async 2.0.0 (dart-lang/stream_channel#10) --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8d44b214a7..a1cf9edec8 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.2 + +* Declare support for `async` 2.0.0. + ## 1.6.1 * Fix the type of `StreamChannel.transform()`. This previously inverted the diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 2d863620be..fee64337ee 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_channel -version: 1.6.2-dev +version: 1.6.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.21.0 <2.0.0' dependencies: - async: '^1.11.0' + async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.18' From dc0bf362a58ad38e78d04d1b3e4032abb3d3c941 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 20 Nov 2017 13:49:39 -0800 Subject: [PATCH 041/138] Use pumpEventQueue() from test (dart-lang/stream_channel#12) --- pkgs/stream_channel/pubspec.yaml | 4 ++-- .../test/disconnector_test.dart | 2 -- .../test/isolate_channel_test.dart | 2 -- .../test/multi_channel_test.dart | 2 -- .../test/stream_channel_completer_test.dart | 2 -- pkgs/stream_channel/test/utils.dart | 19 ------------------- .../test/with_close_guarantee_test.dart | 2 -- .../test/with_guarantees_test.dart | 2 -- 8 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 pkgs/stream_channel/test/utils.dart diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index fee64337ee..6faac8570c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.2 +version: 1.6.3-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel @@ -9,4 +9,4 @@ dependencies: async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' dev_dependencies: - test: '^0.12.18' + test: '^0.12.28' diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index cd1300c665..5b725740c7 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -8,8 +8,6 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index b3b252e6eb..66834cace8 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -8,8 +8,6 @@ import 'dart:isolate'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var receivePort; var sendPort; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index b1156738a7..2a87cafa31 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -5,8 +5,6 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var controller; var channel1; diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index e08dd8a7ac..8d830058a3 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var completer; var streamController; diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart deleted file mode 100644 index e533895401..0000000000 --- a/pkgs/stream_channel/test/utils.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016, 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'; - -/// Returns a [Future] that completes after pumping the event queue [times] -/// times. -/// -/// By default, this should pump the event queue enough times to allow any code -/// to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times = 20]) { - if (times == 0) return new Future.value(); - // Use [new Future] future to allow microtask events to finish. The [new - // Future.value] constructor uses scheduleMicrotask itself and would therefore - // not wait for microtask callbacks that are scheduled after invoking this - // method. - return new Future(() => pumpEventQueue(times - 1)); -} diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index bed6f0db6c..a6527a7163 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -8,8 +8,6 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - final _delayTransformer = new StreamTransformer.fromHandlers( handleData: (data, sink) => new Future.microtask(() => sink.add(data)), handleDone: (sink) => new Future.microtask(() => sink.close())); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 07dd8e52f2..e1302f64c1 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; From 677ee9a08c296eb78feed772c195e3d266aa2efc Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Tue, 19 Dec 2017 13:07:03 -0800 Subject: [PATCH 042/138] prep for release --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a1cf9edec8..ece9e1d5a4 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.3 + +* Use `pumpEventQueue()` from test. + ## 1.6.2 * Declare support for `async` 2.0.0. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 6faac8570c..9a123b1288 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.3-dev +version: 1.6.3 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 4c5a9c982d18be77a2b244d4f4cfdef64dbafb6f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Feb 2018 13:12:32 -0800 Subject: [PATCH 043/138] Stop testing on Dartium (dart-lang/stream_channel#15) Fixes https://github.com/dart-lang/stream_channel/issues/14 --- pkgs/stream_channel/.travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index d5c64e9dde..a9510326d2 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,13 +1,12 @@ language: dart -sudo: false + dart: - dev - stable + dart_task: - test: --platform vm - test: --platform firefox -j 1 - - test: --platform dartium - install_dartium: true - dartfmt - dartanalyzer From 7a53d88bd342312efa6cb4dce0f2c57d62f4e1cf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 27 Feb 2018 14:59:26 -0800 Subject: [PATCH 044/138] Fix a race condition (dart-lang/stream_channel#16) MultiChannel wasn't buffering incoming remote events if their virtual channels hadn't been created locally yet. --- pkgs/stream_channel/CHANGELOG.md | 6 ++ .../stream_channel/lib/src/multi_channel.dart | 61 +++++++++++++------ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 26 ++++++++ 4 files changed, 75 insertions(+), 20 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ece9e1d5a4..093a2421d5 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.4 + +* Fix a race condition in `MultiChannel` where messages from a remote virtual + channel could get dropped if the corresponding local channel wasn't registered + quickly enough. + ## 1.6.3 * Use `pumpEventQueue()` from test. diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 112997e57e..e541543045 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -93,10 +93,18 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The controller for this channel. final _mainController = new StreamChannelController(sync: true); - /// A map from virtual channel ids to [StreamChannelController]s that should - /// be used to communicate over those channels. + /// A map from input IDs to [StreamChannelController]s that should be used to + /// communicate over those channels. final _controllers = {}; + /// Input IDs of controllers in [_controllers] that we've received messages + /// for but that have not yet had a local [virtualChannel] created. + final _pendingIds = new Set(); + + /// Input IDs of virtual channels that used to exist but have since been + /// closed. + final _closedIds = new Set(); + /// The next id to use for a local virtual channel. /// /// Ids are used to identify virtual channels. Each message is tagged with an @@ -114,8 +122,9 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The trick is that each endpoint only uses odd ids for its own channels. /// When sending a message over a channel that was created by the remote /// endpoint, the channel's id plus one is used. This way each [MultiChannel] - /// knows that if an incoming message has an odd id, it's using the local id - /// scheme, but if it has an even id, it's using the remote id scheme. + /// knows that if an incoming message has an odd id, it's coming from a + /// channel that was originally created remotely, but if it has an even id, + /// it's coming from a channel that was originally created locally. var _nextId = 1; _MultiChannel(this._inner) { @@ -128,21 +137,28 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; - var controller = _controllers[id]; - // A controller might not exist if the channel was closed before an - // incoming message was processed. - if (controller == null) return; + // If the channel was closed before an incoming message was processed, + // ignore that message. + if (_closedIds.contains(id)) return; + + var controller = _controllers.putIfAbsent(id, () { + // If we receive a message for a controller that doesn't have a local + // counterpart yet, create a controller for it to buffer incoming + // messages for when a local connection is created. + _pendingIds.add(id); + return new StreamChannelController(sync: true); + }); + if (message.length > 1) { controller.local.sink.add(message[1]); - return; + } else { + // A message without data indicates that the channel has been closed. We + // can just close the sink here without doing any more cleanup, because + // the sink closing will cause the stream to emit a done event which + // will trigger more cleanup. + controller.local.sink.close(); } - - // A message without data indicates that the channel has been closed. We - // can only close the sink here without doing any more cleanup, because - // the sink closing will cause the stream to emit a done event which will - // trigger more cleanup. - controller.local.sink.close(); }, onDone: _closeInnerChannel, onError: _mainController.local.sink.addError); @@ -173,16 +189,22 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { this, inputId, new Stream.empty(), new NullStreamSink()); } - if (_controllers.containsKey(inputId)) { + StreamChannelController controller; + if (_pendingIds.remove(inputId)) { + // If we've already received messages for this channel, use the controller + // where those messages are buffered. + controller = _controllers[inputId]; + } else if (_controllers.containsKey(inputId) || + _closedIds.contains(inputId)) { throw new ArgumentError("A virtual channel with id $id already exists."); + } else { + controller = new StreamChannelController(sync: true); + _controllers[inputId] = controller; } - var controller = new StreamChannelController(sync: true); - _controllers[inputId] = controller; controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); - return new VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); } @@ -190,6 +212,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// Closes the virtual channel for which incoming messages have [inputId] and /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { + _closedIds.add(inputId); var controller = _controllers.remove(inputId); controller.local.sink.close(); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9a123b1288..393e60f3b6 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.3 +version: 1.6.4 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 2a87cafa31..0c9316abb8 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -268,6 +268,32 @@ void main() { test("doesn't allow another virtual channel with the same id", () { expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); + + test("dispatches events received before the virtual channel is created", + () async { + virtual1 = channel1.virtualChannel(); + + virtual1.sink.add("hello"); + await pumpEventQueue(); + + virtual1.sink.add("world"); + await pumpEventQueue(); + + expect(channel2.virtualChannel(virtual1.id).stream, + emitsInOrder(["hello", "world"])); + }); + + test( + "dispatches close events received before the virtual channel is " + "created", () async { + virtual1 = channel1.virtualChannel(); + + virtual1.sink.close(); + await pumpEventQueue(); + + expect(channel2.virtualChannel(virtual1.id).stream.toList(), + completion(isEmpty)); + }); }); group("when the underlying stream", () { From 7b0392bef85ec2f8d61ee1221e0b6c774e47cf0f Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 11:57:37 -0700 Subject: [PATCH 045/138] make sure the inner sink is properly typed in JsonDocumentTransformer.bind --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 86b9ae71c3..40e5155a9f 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -2,6 +2,7 @@ // 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 'dart:convert'; import 'package:async/async.dart'; @@ -35,9 +36,10 @@ class JsonDocumentTransformer JsonDocumentTransformer._(this._codec); - StreamChannel bind(StreamChannel channel) { + StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { + var sink = new StreamSinkTransformer.fromHandlers( + handleData: (Object data, EventSink sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); return new StreamChannel.withCloseGuarantee(stream, sink); From 4e385426b1e7c144406f515903f093ec2120f83e Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 11:59:09 -0700 Subject: [PATCH 046/138] update pubspec/changelog --- pkgs/stream_channel/CHANGELOG.md | 5 +++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 093a2421d5..d15b0c032d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.4+1 + +* Fix an issue with `JsonDocumentTransformer.bind` where it created an internal + stream channel which didn't get a properly inferred type for its `sink`. + ## 1.6.4 * Fix a race condition in `MultiChannel` where messages from a remote virtual diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 393e60f3b6..5abd523ee0 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4 +version: 1.6.4+5 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 3b092fb932e61a7cbcd70f25dfe75b7b1d1fa80a Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 12:11:25 -0700 Subject: [PATCH 047/138] fix pubspec version to match changelog --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5abd523ee0..09179771c8 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4+5 +version: 1.6.4+1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From c4dcc8d1a0a39fec7d05346f87531b96c50b4573 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 13:48:36 -0700 Subject: [PATCH 048/138] code review updates --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/lib/src/json_document_transformer.dart | 4 ++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index d15b0c032d..4813e9a1fe 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.6.4+1 +## 1.6.5 * Fix an issue with `JsonDocumentTransformer.bind` where it created an internal stream channel which didn't get a properly inferred type for its `sink`. diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 40e5155a9f..533d238239 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -38,8 +38,8 @@ class JsonDocumentTransformer StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers( - handleData: (Object data, EventSink sink) { + var sink = new StreamSinkTransformer.fromHandlers( + handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); return new StreamChannel.withCloseGuarantee(stream, sink); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 09179771c8..9221866dc5 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4+1 +version: 1.6.5 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 278de144374bce9c49f16384f6f428d01b02e342 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 17 Apr 2018 14:13:30 -0700 Subject: [PATCH 049/138] Upgrade some hints to errors (dart-lang/stream_channel#19) These prevent building internally. Fix an unused import. --- pkgs/stream_channel/analysis_options.yaml | 6 ++++++ pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index a10d4c5a05..743cc902d5 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,2 +1,8 @@ analyzer: strong-mode: true + # These are errors when building in Google + errors: + unused_import: error + unused_element: error + unused_local_variable: error + dead_code: error diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 533d238239..6377eeda7e 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -2,7 +2,6 @@ // 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 'dart:convert'; import 'package:async/async.dart'; From 51947287a3bf2323d86933187c51c203d48ec0d6 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 08:02:29 -0700 Subject: [PATCH 050/138] fix tests for dart 2 --- pkgs/stream_channel/lib/src/guarantee_channel.dart | 2 +- pkgs/stream_channel/test/json_document_transformer_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index f18cbb9733..ba79ed9bcd 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -39,7 +39,7 @@ class GuaranteeChannel extends StreamChannelMixin { // to single-subscription. if (innerStream.isBroadcast) { innerStream = - innerStream.transform(const SingleSubscriptionTransformer()); + innerStream.transform(new SingleSubscriptionTransformer()); } _streamController = new StreamController( diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 22bb830093..b55a118879 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -13,8 +13,8 @@ void main() { var sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); + streamController = new StreamController(); + sinkController = new StreamController(); channel = new StreamChannel(streamController.stream, sinkController.sink); }); From b32ad837ec902416a1846bde58a307e57d3e8fa8 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 08:06:51 -0700 Subject: [PATCH 051/138] update changelog/pubspec --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4813e9a1fe..a2404d27ea 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.6 + +* Fix a Dart2 issue with inner stream transformation in `GuaranteeChannel`. + ## 1.6.5 * Fix an issue with `JsonDocumentTransformer.bind` where it created an internal diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9221866dc5..c121f5f132 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.5 +version: 1.6.6 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 99325e82bfb017f4edd275bdb7a159ef94a638e2 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 09:58:15 -0700 Subject: [PATCH 052/138] fix some stream channel tests --- pkgs/stream_channel/.gitignore | 1 + .../test/stream_channel_test.dart | 43 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pkgs/stream_channel/.gitignore b/pkgs/stream_channel/.gitignore index 25a1df3326..1447012ea0 100644 --- a/pkgs/stream_channel/.gitignore +++ b/pkgs/stream_channel/.gitignore @@ -1,4 +1,5 @@ .buildlog +.dart_tool/ .DS_Store .idea .pub/ diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index b8ebcbd854..c29002fdfc 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -10,9 +10,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var channel; + StreamController streamController; + StreamController sinkController; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); @@ -58,36 +58,35 @@ void main() { }); test("transformStream() transforms only the stream", () async { - var transformed = channel.transformStream(UTF8.decoder); + var transformed = + channel.cast().transformStream(const LineSplitter()); - streamController.add([102, 111, 111, 98, 97, 114]); + streamController.add("hello world"); + streamController.add(" what\nis"); + streamController.add("\nup"); streamController.close(); - expect(await transformed.stream.toList(), equals(["foobar"])); + expect(await transformed.stream.toList(), + equals(["hello world what", "is", "up"])); - transformed.sink.add("fblthp"); + transformed.sink.add("fbl\nthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), completion(equals(["fblthp"]))); + expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); }); test("transformSink() transforms only the sink", () async { - var transformed = channel.transformSink( - new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); + var transformed = channel.cast().transformSink( + new StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); - streamController.add([102, 111, 111, 98, 97, 114]); + streamController.add("fbl\nthp"); streamController.close(); - expect( - await transformed.stream.toList(), - equals([ - [102, 111, 111, 98, 97, 114] - ])); + expect(await transformed.stream.toList(), equals(["fbl\nthp"])); - transformed.sink.add("fblthp"); + transformed.sink.add("hello world"); + transformed.sink.add(" what\nis"); + transformed.sink.add("\nup"); transformed.sink.close(); - expect( - sinkController.stream.toList(), - completion(equals([ - [102, 98, 108, 116, 104, 112] - ]))); + expect(sinkController.stream.toList(), + completion(equals(["hello world what", "is", "up"]))); }); test("changeStream() changes the stream", () { From 509e7364b58c6db8b8ecd1e7dd358383d63561f7 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 May 2018 12:51:37 -0700 Subject: [PATCH 053/138] Fix a remaining Dart 2 issue (dart-lang/stream_channel#23) We had some unnecessary typed wrappers that were interfering with runtime type arguments. Closes dart-lang/stream_channel#22 --- pkgs/stream_channel/CHANGELOG.md | 4 +++- .../stream_channel/lib/src/stream_channel_transformer.dart | 7 ++----- pkgs/stream_channel/test/stream_channel_test.dart | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a2404d27ea..014b2fcc35 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,8 @@ ## 1.6.6 -* Fix a Dart2 issue with inner stream transformation in `GuaranteeChannel`. +* Fix a Dart 2 issue with inner stream transformation in `GuaranteeChannel`. + +* Fix a Dart 2 issue with `StreamChannelTransformer.fromCodec()`. ## 1.6.5 diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 1a4afcae2b..4fcd3cd697 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -57,11 +57,8 @@ class StreamChannelTransformer { /// All input to the inner channel's sink is encoded using [Codec.encoder], /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) - : this( - typedStreamTransformer(codec.decoder), - StreamSinkTransformer.typed( - new StreamSinkTransformer.fromStreamTransformer( - codec.encoder))); + : this(codec.decoder, + new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index c29002fdfc..4ec84bc264 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,8 +41,9 @@ void main() { }); test("transform() transforms the channel", () async { - var transformed = - channel.transform(new StreamChannelTransformer.fromCodec(UTF8)); + var transformed = channel + .cast>() + .transform(new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 9a1991971381e2a2ecd7d7285bb5f74f55e52dfe Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Sun, 20 May 2018 13:28:26 +0100 Subject: [PATCH 054/138] Stop testing IsolateChannel on browsers (dart-lang/stream_channel#24) --- pkgs/stream_channel/test/isolate_channel_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 66834cace8..8f33184691 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('vm') + import 'dart:async'; import 'dart:isolate'; From dbe4ec143efd91a28d76a89f845669adc8ec7095 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 1 Jun 2018 14:57:12 +0200 Subject: [PATCH 055/138] Remove upper case constants (dart-lang/stream_channel#17) * Remove usage of upper-case constants. * update SDK version * remove stable from Travis config --- pkgs/stream_channel/.travis.yml | 2 -- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- pkgs/stream_channel/test/json_document_transformer_test.dart | 2 +- pkgs/stream_channel/test/stream_channel_test.dart | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index a9510326d2..45359fb404 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -2,8 +2,6 @@ language: dart dart: - dev - - stable - dart_task: - test: --platform vm - test: --platform firefox -j 1 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 014b2fcc35..eafdb81223 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.7 + +* Update SDK version to 2.0.0-dev.17.0. + ## 1.6.6 * Fix a Dart 2 issue with inner stream transformation in `GuaranteeChannel`. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c121f5f132..47e24c2f75 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,10 @@ name: stream_channel -version: 1.6.6 +version: 1.6.7-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.21.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index b55a118879..d6fd72b965 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -29,7 +29,7 @@ void main() { var transformed = channel.transform(jsonDocument); transformed.sink.add({"foo": "bar"}); expect(sinkController.stream.first, - completion(equals(JSON.encode({"foo": "bar"})))); + completion(equals(jsonEncode({"foo": "bar"})))); }); test("supports the reviver function", () { diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 4ec84bc264..dbe4211956 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -43,7 +43,7 @@ void main() { test("transform() transforms the channel", () async { var transformed = channel .cast>() - .transform(new StreamChannelTransformer.fromCodec(UTF8)); + .transform(new StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 533026d8efb58d8c68bcbc977ee69b4aff091ecd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 14:59:31 -0700 Subject: [PATCH 056/138] Allow a type on MultiChannel (dart-lang/stream_channel#26) - Add generic type arguments to the classes and relevant fields. - Explicitly indicate which arguments take a `StreamChannel`. - Update the test for MultiChannel to use a consistent type. --- pkgs/stream_channel/CHANGELOG.md | 1 + .../stream_channel/lib/src/multi_channel.dart | 41 +++++++++-------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 45 +++++++++---------- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index eafdb81223..b284e5ed87 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.6.7 * Update SDK version to 2.0.0-dev.17.0. +* Add a type argument to `MultiChannel`. ## 1.6.6 diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e541543045..e7e2584aac 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -41,24 +41,25 @@ import '../stream_channel.dart'; /// /// Each virtual channel may be closed individually. When all of them are /// closed, the underlying [StreamSink] is closed automatically. -abstract class MultiChannel implements StreamChannel { +abstract class MultiChannel implements StreamChannel { /// The default input stream. /// /// This connects to the remote [sink]. - Stream get stream; + Stream get stream; /// The default output stream. /// /// This connects to the remote [stream]. If this is closed, the remote /// [stream] will close, but other virtual channels will remain open and new /// virtual channels may be opened. - StreamSink get sink; + StreamSink get sink; /// Creates a new [MultiChannel] that sends and receives messages over /// [inner]. /// /// The inner channel must take JSON-like objects. - factory MultiChannel(StreamChannel inner) => new _MultiChannel(inner); + factory MultiChannel(StreamChannel inner) => + new _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -71,31 +72,32 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([id]); + VirtualChannel virtualChannel([id]); } /// The implementation of [MultiChannel]. /// /// This is private so that [VirtualChannel] can inherit from [MultiChannel] /// without having to implement all the private members. -class _MultiChannel extends StreamChannelMixin implements MultiChannel { +class _MultiChannel extends StreamChannelMixin + implements MultiChannel { /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - StreamChannel _inner; + StreamChannel _inner; /// The subscription to [_inner.stream]. - StreamSubscription _innerStreamSubscription; + StreamSubscription _innerStreamSubscription; - Stream get stream => _mainController.foreign.stream; - StreamSink get sink => _mainController.foreign.sink; + Stream get stream => _mainController.foreign.stream; + StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. - final _mainController = new StreamChannelController(sync: true); + final _mainController = new StreamChannelController(sync: true); /// A map from input IDs to [StreamChannelController]s that should be used to /// communicate over those channels. - final _controllers = {}; + final _controllers = >{}; /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. @@ -164,7 +166,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { onError: _mainController.local.sink.addError); } - VirtualChannel virtualChannel([id]) { + VirtualChannel virtualChannel([id]) { var inputId; var outputId; if (id != null) { @@ -189,7 +191,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { this, inputId, new Stream.empty(), new NullStreamSink()); } - StreamChannelController controller; + StreamChannelController controller; if (_pendingIds.remove(inputId)) { // If we've already received messages for this channel, use the controller // where those messages are buffered. @@ -244,9 +246,10 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// This implements [MultiChannel] for convenience. /// [VirtualChannel.virtualChannel] is semantically identical to the parent's /// [MultiChannel.virtualChannel]. -class VirtualChannel extends StreamChannelMixin implements MultiChannel { +class VirtualChannel extends StreamChannelMixin + implements MultiChannel { /// The [MultiChannel] that created this. - final MultiChannel _parent; + final MultiChannel _parent; /// The identifier for this channel. /// @@ -255,10 +258,10 @@ class VirtualChannel extends StreamChannelMixin implements MultiChannel { /// except that it will be JSON-serializable. final id; - final Stream stream; - final StreamSink sink; + final Stream stream; + final StreamSink sink; VirtualChannel._(this._parent, this.id, this.stream, this.sink); - VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); + VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 47e24c2f75..bbb29d8b77 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.7-dev +version: 1.6.7 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0c9316abb8..99a53c328a 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -11,8 +11,8 @@ void main() { var channel2; setUp(() { controller = new StreamChannelController(); - channel1 = new MultiChannel(controller.local); - channel2 = new MultiChannel(controller.foreign); + channel1 = new MultiChannel(controller.local); + channel2 = new MultiChannel(controller.foreign); }); group("the default virtual channel", () { @@ -20,15 +20,15 @@ void main() { var first = true; channel2.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); - channel1.sink.add("hello"); - channel1.sink.add("world"); + channel1.sink.add(1); + channel1.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -95,10 +95,10 @@ void main() { var first = true; virtual2.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); @@ -109,8 +109,8 @@ void main() { } channel2.stream.listen(expectAsync1((_) {}, count: 0)); - virtual1.sink.add("hello"); - virtual1.sink.add("world"); + virtual1.sink.add(1); + virtual1.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -174,12 +174,12 @@ void main() { expect(virtual1.id, equals(virtual3.id)); virtual2.stream - .listen(expectAsync1((message) => expect(message, equals("hello")))); - virtual4.stream.listen( - expectAsync1((message) => expect(message, equals("goodbye")))); + .listen(expectAsync1((message) => expect(message, equals(1)))); + virtual4.stream + .listen(expectAsync1((message) => expect(message, equals(2)))); - virtual1.sink.add("hello"); - virtual3.sink.add("goodbye"); + virtual1.sink.add(1); + virtual3.sink.add(2); }); }); @@ -195,10 +195,10 @@ void main() { var first = true; virtual1.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); @@ -209,8 +209,8 @@ void main() { } channel1.stream.listen(expectAsync1((_) {}, count: 0)); - virtual2.sink.add("hello"); - virtual2.sink.add("world"); + virtual2.sink.add(1); + virtual2.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -273,14 +273,13 @@ void main() { () async { virtual1 = channel1.virtualChannel(); - virtual1.sink.add("hello"); + virtual1.sink.add(1); await pumpEventQueue(); - virtual1.sink.add("world"); + virtual1.sink.add(2); await pumpEventQueue(); - expect(channel2.virtualChannel(virtual1.id).stream, - emitsInOrder(["hello", "world"])); + expect(channel2.virtualChannel(virtual1.id).stream, emitsInOrder([1, 2])); }); test( From 58810c95b4898e49b0ee681f8aff4d9fbce4a52b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 14:59:51 -0700 Subject: [PATCH 057/138] Drop dependency on StackTrace (dart-lang/stream_channel#27) The extra wrapping of `StackTrace.current` can always be done by the receiver. --- pkgs/stream_channel/lib/src/isolate_channel.dart | 3 +-- pkgs/stream_channel/pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index f1328c03d1..290c2ff2ce 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:isolate'; import 'package:async/async.dart'; -import 'package:stack_trace/stack_trace.dart'; import '../stream_channel.dart'; @@ -66,7 +65,7 @@ class IsolateChannel extends StreamChannelMixin { streamCompleter.setError( new StateError('Unexpected Isolate response "$message".'), - new Trace.current()); + StackTrace.current); sinkCompleter.setDestinationSink(new NullStreamSink()); subscription.cancel(); }); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bbb29d8b77..ff2209c944 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,6 +7,5 @@ environment: sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: async: '>=1.11.0 <3.0.0' - stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.28' From ff1febd21c1b5e137bd70997a0b54581319fad1e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 15:40:42 -0700 Subject: [PATCH 058/138] Fix doc comment references (dart-lang/stream_channel#28) --- pkgs/stream_channel/analysis_options.yaml | 4 +++ .../stream_channel/lib/src/multi_channel.dart | 2 +- .../lib/src/stream_channel_controller.dart | 4 +-- .../lib/src/stream_channel_transformer.dart | 4 +-- pkgs/stream_channel/lib/stream_channel.dart | 30 +++++++++---------- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 743cc902d5..107424e55d 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -6,3 +6,7 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error + +linter: + rules: + - comment_references diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e7e2584aac..a1ee0574f6 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -86,7 +86,7 @@ class _MultiChannel extends StreamChannelMixin /// This will be `null` if the underlying communication channel is closed. StreamChannel _inner; - /// The subscription to [_inner.stream]. + /// The subscription to [_inner].stream. StreamSubscription _innerStreamSubscription; Stream get stream => _mainController.foreign.stream; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 45b2865ed3..146e99667f 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -50,8 +50,8 @@ class StreamChannelController { /// /// If [allowForeignErrors] is `false`, errors are not allowed to be passed to /// the foreign channel's sink. If any are, the connection will close and the - /// error will be forwarded to the foreign channel's [Sink.done] future. This - /// guarantees that the local stream will never emit errors. + /// error will be forwarded to the foreign channel's [StreamSink.done] future. + /// This guarantees that the local stream will never emit errors. StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { var localToForeignController = new StreamController(sync: sync); var foreignToLocalController = new StreamController(sync: sync); diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 4fcd3cd697..cc9bad881b 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -23,8 +23,8 @@ import 'transformer/typed.dart'; /// the stream to close before it emits any more events. This guarantee is /// invalidated when an asynchronous gap is added between the original stream's /// event dispatch and the returned stream's, for example by transforming it -/// with a [StreamTransformer]. The guarantee can be easily preserved using [new -/// StreamChannel.withCloseGuarantee]. +/// with a [StreamTransformer]. The guarantee can be easily preserved using +/// [StreamChannel.withCloseGuarantee]. class StreamChannelTransformer { /// The transformer to use on the channel's stream. final StreamTransformer _streamTransformer; diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 8d0e60421f..ce3cf04a70 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -25,8 +25,8 @@ export 'src/stream_channel_transformer.dart'; /// canonical indicator that the channel has closed. If they wish to close the /// channel, they should close the [sink]—canceling the stream subscription is /// not sufficient. Protocol errors may be emitted through the stream or through -/// [Sink.done], depending on their underlying cause. Note that the sink may -/// silently drop events if the channel closes before [Sink.close] is called. +/// [sink].done, depending on their underlying cause. Note that the sink may +/// silently drop events if the channel closes before [sink].close is called. /// /// Implementations are strongly encouraged to mix in or extend /// [StreamChannelMixin] to get default implementations of the various instance @@ -43,7 +43,7 @@ export 'src/stream_channel_transformer.dart'; /// /// * After the stream closes, the sink is automatically closed. If this /// happens, sink methods should silently drop their arguments until -/// [Sink.close] is called. +/// [sink].close is called. /// /// * If the stream closes before it has a listener, the sink should silently /// drop events if possible. @@ -53,7 +53,7 @@ export 'src/stream_channel_transformer.dart'; /// even after the subscription has been canceled. /// /// * The sink *either* forwards errors to the other endpoint *or* closes as -/// soon as an error is added and forwards that error to the [Sink.done] +/// soon as an error is added and forwards that error to the [sink].done /// future. /// /// These guarantees allow users to interact uniformly with all implementations, @@ -69,8 +69,8 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// /// Note that this stream/sink pair must provide the guarantees listed in the - /// [StreamChannel] documentation. If they don't do so natively, [new - /// StreamChannel.withGuarantees] should be used instead. + /// [StreamChannel] documentation. If they don't do so natively, + /// [StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); @@ -83,7 +83,7 @@ abstract class StreamChannel { /// /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to /// [sink]. If any are, the connection will close and the error will be - /// forwarded to [Sink.done]. + /// forwarded to [sink].done. factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, {bool allowSinkErrors: true}) => new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); @@ -101,33 +101,33 @@ abstract class StreamChannel { Stream stream, StreamSink sink) => new CloseGuaranteeChannel(stream, sink); - /// Connects [this] to [other], so that any values emitted by either are sent + /// Connects this to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); - /// Transforms [this] using [transformer]. + /// Transforms this using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. StreamChannel transform(StreamChannelTransformer transformer); - /// Transforms only the [stream] component of [this] using [transformer]. + /// Transforms only the [stream] component of this using [transformer]. StreamChannel transformStream(StreamTransformer transformer); - /// Transforms only the [sink] component of [this] using [transformer]. + /// Transforms only the [sink] component of this using [transformer]. StreamChannel transformSink(StreamSinkTransformer transformer); - /// Returns a copy of [this] with [stream] replaced by [change]'s return + /// Returns a copy of this with [stream] replaced by [change]'s return /// value. StreamChannel changeStream(Stream change(Stream stream)); - /// Returns a copy of [this] with [sink] replaced by [change]'s return + /// Returns a copy of this with [sink] replaced by [change]'s return /// value. StreamChannel changeSink(StreamSink change(StreamSink sink)); - /// Returns a copy of [this] with the generic type coerced to [S]. + /// Returns a copy of this with the generic type coerced to [S]. /// /// If any events emitted by [stream] aren't of type [S], they're converted - /// into [CastError] events. Similarly, if any events are added to [sync] that + /// into [CastError] events. Similarly, if any events are added to [sink] that /// aren't of type [S], a [CastError] is thrown. StreamChannel cast(); } From b0dc30207fa6f5c617f0618ed3edc22b75f1da74 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Jun 2018 09:27:35 -0700 Subject: [PATCH 059/138] Enable prefer_typing_unitialized_varables lint (dart-lang/stream_channel#30) Work towards dart-lang/stream_channel#29 Using the lint catches a bug were an uninitialized variable was causing an instantiation to pick up a reified type of `dynamic` instead of a useful type. --- pkgs/stream_channel/analysis_options.yaml | 1 + .../lib/src/isolate_channel.dart | 2 +- .../stream_channel/lib/src/multi_channel.dart | 12 +++++----- .../test/disconnector_test.dart | 8 +++---- .../test/isolate_channel_test.dart | 8 +++---- .../test/json_document_transformer_test.dart | 4 ++-- .../test/multi_channel_test.dart | 22 +++++++++---------- .../test/stream_channel_completer_test.dart | 8 +++---- .../test/stream_channel_controller_test.dart | 4 ++-- .../test/with_close_guarantee_test.dart | 4 ++-- .../test/with_guarantees_test.dart | 6 ++--- 11 files changed, 40 insertions(+), 39 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 107424e55d..bf7c331dd7 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -10,3 +10,4 @@ analyzer: linter: rules: - comment_references + - prefer_typing_uninitialized_variables diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 290c2ff2ce..4a1717df11 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -49,7 +49,7 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - var subscription; + StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = new StreamChannelController( diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a1ee0574f6..a6d684a134 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -72,7 +72,7 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([id]); + VirtualChannel virtualChannel([int id]); } /// The implementation of [MultiChannel]. @@ -166,15 +166,15 @@ class _MultiChannel extends StreamChannelMixin onError: _mainController.local.sink.addError); } - VirtualChannel virtualChannel([id]) { - var inputId; - var outputId; + VirtualChannel virtualChannel([int id]) { + int inputId; + int outputId; if (id != null) { // Since the user is passing in an id, we're connected to a remote // VirtualChannel. This means messages they send over this channel will // have the original odd id, but our replies will have an even id. inputId = id; - outputId = (id as int) + 1; + outputId = id + 1; } else { // Since we're generating an id, we originated this VirtualChannel. This // means messages we send over this channel will have the original odd id, @@ -256,7 +256,7 @@ class VirtualChannel extends StreamChannelMixin /// This can be sent across the [MultiChannel] to provide the remote endpoint /// a means to connect to this channel. Nothing about this is guaranteed /// except that it will be JSON-serializable. - final id; + final int id; final Stream stream; final StreamSink sink; diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 5b725740c7..62ef78b546 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -9,10 +9,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var disconnector; - var channel; + StreamController streamController; + StreamController sinkController; + Disconnector disconnector; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 8f33184691..00f45844c2 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -11,9 +11,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var receivePort; - var sendPort; - var channel; + ReceivePort receivePort; + SendPort sendPort; + StreamChannel channel; setUp(() { receivePort = new ReceivePort(); var receivePortForSend = new ReceivePort(); @@ -126,7 +126,7 @@ void main() { }); group("connect constructors", () { - var connectPort; + ReceivePort connectPort; setUp(() { connectPort = new ReceivePort(); }); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index d6fd72b965..3c6d11c915 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -9,8 +9,8 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; + StreamController streamController; + StreamController sinkController; StreamChannel channel; setUp(() { streamController = new StreamController(); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 99a53c328a..ddc4150bbc 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -6,9 +6,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var controller; - var channel1; - var channel2; + StreamChannelController controller; + MultiChannel channel1; + MultiChannel channel2; setUp(() { controller = new StreamChannelController(); channel1 = new MultiChannel(controller.local); @@ -84,8 +84,8 @@ void main() { }); group("a locally-created virtual channel", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -184,8 +184,8 @@ void main() { }); group("a remotely-created virtual channel", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -296,8 +296,8 @@ void main() { }); group("when the underlying stream", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -405,8 +405,8 @@ void main() { }); group("for a virtual channel:", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 8d830058a3..666efe9ede 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -8,10 +8,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var completer; - var streamController; - var sinkController; - var innerChannel; + StreamChannelCompleter completer; + StreamController streamController; + StreamController sinkController; + StreamChannel innerChannel; setUp(() { completer = new StreamChannelCompleter(); streamController = new StreamController(); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index c092570f58..483b7f6f1f 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -7,7 +7,7 @@ import 'package:test/test.dart'; void main() { group("asynchronously", () { - var controller; + StreamChannelController controller; setUp(() { controller = new StreamChannelController(); }); @@ -44,7 +44,7 @@ void main() { }); group("synchronously", () { - var controller; + StreamChannelController controller; setUp(() { controller = new StreamChannelController(sync: true); }); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index a6527a7163..8e1b63119f 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -16,8 +16,8 @@ final _delaySinkTransformer = new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { - var controller; - var channel; + StreamChannelController controller; + StreamChannel channel; setUp(() { controller = new StreamChannelController(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index e1302f64c1..dcdffe0891 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -8,9 +8,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var channel; + StreamController streamController; + StreamController sinkController; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); From 338ee53371ac67e88a094bb4fcb6af73075edfa4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Jun 2018 10:53:40 -0700 Subject: [PATCH 060/138] Cast streams to correct types in IsolateChannel (dart-lang/stream_channel#31) Fixes dart-lang/stream_channel#29 - Add a type on the IsolateChannel in one of the tests so that it exhibits the problem when run in Dart 2 mode. - Cast the streams coming from the ReceivePort instances to the appropriate types since ReceivePort is always `Stream`. - Remove the type on the subscription variable since it's a subscription on a dynamic stream and otherwise would never have the correct type. --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 8 +++++--- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index b284e5ed87..3dfbbc6f9e 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.7+1 + +* Fix Dart 2 runtime types in `IsolateChannel`. + ## 1.6.7 * Update SDK version to 2.0.0-dev.17.0. diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 4a1717df11..d785ae118c 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -49,12 +49,14 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - StreamSubscription subscription; + StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = new StreamChannelController( allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription).pipe(controller.local.sink); + new SubscriptionStream(subscription) + .cast() + .pipe(controller.local.sink); controller.local.stream .listen((data) => message.send(data), onDone: receivePort.close); @@ -93,7 +95,7 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { var controller = new StreamChannelController(allowForeignErrors: false, sync: true); - receivePort.pipe(controller.local.sink); + receivePort.cast().pipe(controller.local.sink); controller.local.stream .listen((data) => sendPort.send(data), onDone: receivePort.close); return new IsolateChannel._( diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index ff2209c944..54bd972176 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.7 +version: 1.6.7+1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 00f45844c2..4c73ab090c 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -136,8 +136,8 @@ void main() { }); test("create a connected pair of channels", () { - var channel1 = new IsolateChannel.connectReceive(connectPort); - var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + var channel1 = new IsolateChannel.connectReceive(connectPort); + var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); From 19ba981cfb19b60437170202d27c18cc2ce98527 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Jul 2018 19:28:11 -0400 Subject: [PATCH 061/138] Allow SDK versions <3.0.0 (dart-lang/stream_channel#32) And update some dependencies. --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/analysis_options.yaml | 1 - pkgs/stream_channel/pubspec.yaml | 10 +++++++--- .../test/json_document_transformer_test.dart | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 3dfbbc6f9e..ce98fe0387 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.8 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 1.6.7+1 * Fix Dart 2 runtime types in `IsolateChannel`. diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index bf7c331dd7..d19ee843f7 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,5 +1,4 @@ analyzer: - strong-mode: true # These are errors when building in Google errors: unused_import: error diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 54bd972176..6b1ace36f7 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,11 +1,15 @@ name: stream_channel -version: 1.6.7+1 +version: 1.6.8 + description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel + environment: - sdk: '>=2.0.0-dev.17.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <3.0.0' + dependencies: async: '>=1.11.0 <3.0.0' + dev_dependencies: - test: '^0.12.28' + test: ^1.2.0 diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 3c6d11c915..6cb97f9454 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -55,6 +55,6 @@ void main() { test("synchronously throws if an unencodable object is added", () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(new Object()), - throwsA(new isInstanceOf())); + throwsA(new TypeMatcher())); }); } From 3191148f2fa5311d55bf717678e2e8d9dc3bece4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Mar 2019 14:00:09 -0700 Subject: [PATCH 062/138] Remove optional new/const (dart-lang/stream_channel#37) - Run `dartfmt --fix`. - Update version to start working towards next breaking change. - Update minimum SDK to 2.0.0 stable. --- pkgs/stream_channel/CHANGELOG.md | 5 +++ .../lib/src/close_guarantee_channel.dart | 4 +-- pkgs/stream_channel/lib/src/disconnector.dart | 22 ++++++------- .../lib/src/guarantee_channel.dart | 31 +++++++++---------- .../lib/src/isolate_channel.dart | 27 +++++++--------- .../lib/src/json_document_transformer.dart | 8 ++--- .../stream_channel/lib/src/multi_channel.dart | 22 ++++++------- .../lib/src/stream_channel_completer.dart | 15 +++++---- .../lib/src/stream_channel_controller.dart | 10 +++--- .../lib/src/stream_channel_transformer.dart | 6 ++-- pkgs/stream_channel/lib/stream_channel.dart | 14 ++++----- pkgs/stream_channel/pubspec.yaml | 4 +-- .../test/disconnector_test.dart | 28 ++++++++--------- .../test/isolate_channel_test.dart | 22 ++++++------- .../test/json_document_transformer_test.dart | 20 ++++++------ .../test/multi_channel_test.dart | 6 ++-- .../test/stream_channel_completer_test.dart | 14 ++++----- .../test/stream_channel_controller_test.dart | 6 ++-- .../test/stream_channel_test.dart | 22 ++++++------- .../test/with_close_guarantee_test.dart | 12 +++---- .../test/with_guarantees_test.dart | 24 +++++++------- 21 files changed, 159 insertions(+), 163 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ce98fe0387..87ba42fe7d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.9 + +* Require `2.0.0` or newer SDK. +* Drop unnecessary `new` and `const`. + ## 1.6.8 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index a2c69bcb8b..b8a3f02890 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -27,8 +27,8 @@ class CloseGuaranteeChannel extends StreamChannelMixin { bool _disconnected = false; CloseGuaranteeChannel(Stream innerStream, StreamSink innerSink) { - _sink = new _CloseGuaranteeSink(innerSink, this); - _stream = new _CloseGuaranteeStream(innerStream, this); + _sink = _CloseGuaranteeSink(innerSink, this); + _stream = _CloseGuaranteeStream(innerStream, this); } } diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 37a376c312..9d35cfc63f 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,11 +38,11 @@ class Disconnector implements StreamChannelTransformer { _sinks.clear(); return Future.wait(futures, eagerError: true); }); - final _disconnectMemo = new AsyncMemoizer(); + final _disconnectMemo = AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { - var sink = new _DisconnectorSink(innerSink); + var sink = _DisconnectorSink(innerSink); if (isDisconnected) { // Ignore errors here, because otherwise there would be no way for the @@ -84,9 +84,9 @@ class _DisconnectorSink implements StreamSink { _DisconnectorSink(this._inner); void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_isDisconnected) return; @@ -94,9 +94,9 @@ class _DisconnectorSink implements StreamSink { } void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_isDisconnected) return; @@ -104,13 +104,13 @@ class _DisconnectorSink implements StreamSink { } Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); + if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); + throw StateError("Cannot add stream while adding stream."); } - if (_isDisconnected) return new Future.value(); + if (_isDisconnected) return Future.value(); - _addStreamCompleter = new Completer.sync(); + _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, onError: _inner.addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { @@ -121,7 +121,7 @@ class _DisconnectorSink implements StreamSink { Future close() { if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); + throw StateError("Cannot close sink while adding stream."); } _closed = true; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index ba79ed9bcd..e96f5c3c8a 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -31,18 +31,17 @@ class GuaranteeChannel extends StreamChannelMixin { bool _disconnected = false; GuaranteeChannel(Stream innerStream, StreamSink innerSink, - {bool allowSinkErrors: true}) { - _sink = - new _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); + {bool allowSinkErrors = true}) { + _sink = _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. if (innerStream.isBroadcast) { innerStream = - innerStream.transform(new SingleSubscriptionTransformer()); + innerStream.transform(SingleSubscriptionTransformer()); } - _streamController = new StreamController( + _streamController = StreamController( onListen: () { // If the sink has disconnected, we've already called // [_streamController.close]. @@ -80,7 +79,7 @@ class _GuaranteeSink implements StreamSink { final GuaranteeChannel _channel; Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); + final _doneCompleter = Completer(); /// Whether connection is disconnected. /// @@ -108,13 +107,13 @@ class _GuaranteeSink implements StreamSink { /// the underlying sink is closed. final bool _allowErrors; - _GuaranteeSink(this._inner, this._channel, {bool allowErrors: true}) + _GuaranteeSink(this._inner, this._channel, {bool allowErrors = true}) : _allowErrors = allowErrors; void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_disconnected) return; @@ -122,9 +121,9 @@ class _GuaranteeSink implements StreamSink { } void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_disconnected) return; @@ -153,13 +152,13 @@ class _GuaranteeSink implements StreamSink { } Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); + if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); + throw StateError("Cannot add stream while adding stream."); } - if (_disconnected) return new Future.value(); + if (_disconnected) return Future.value(); - _addStreamCompleter = new Completer.sync(); + _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { @@ -170,7 +169,7 @@ class _GuaranteeSink implements StreamSink { Future close() { if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); + throw StateError("Cannot close sink while adding stream."); } if (_closed) return done; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index d785ae118c..c7f573fd2a 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -41,10 +41,10 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel.connectReceive(ReceivePort receivePort) { // We can't use a [StreamChannelCompleter] here because we need the return // value to be an [IsolateChannel]. - var streamCompleter = new StreamCompleter(); - var sinkCompleter = new StreamSinkCompleter(); + var streamCompleter = StreamCompleter(); + var sinkCompleter = StreamSinkCompleter(); var channel = - new IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); + IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error @@ -52,11 +52,9 @@ class IsolateChannel extends StreamChannelMixin { StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController( - allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription) - .cast() - .pipe(controller.local.sink); + var controller = + StreamChannelController(allowForeignErrors: false, sync: true); + SubscriptionStream(subscription).cast().pipe(controller.local.sink); controller.local.stream .listen((data) => message.send(data), onDone: receivePort.close); @@ -66,9 +64,9 @@ class IsolateChannel extends StreamChannelMixin { } streamCompleter.setError( - new StateError('Unexpected Isolate response "$message".'), + StateError('Unexpected Isolate response "$message".'), StackTrace.current); - sinkCompleter.setDestinationSink(new NullStreamSink()); + sinkCompleter.setDestinationSink(NullStreamSink()); subscription.cancel(); }); @@ -85,21 +83,20 @@ class IsolateChannel extends StreamChannelMixin { /// The connection protocol is guaranteed to remain compatible across versions /// at least until the next major version release. factory IsolateChannel.connectSend(SendPort sendPort) { - var receivePort = new ReceivePort(); + var receivePort = ReceivePort(); sendPort.send(receivePort.sendPort); - return new IsolateChannel(receivePort, sendPort); + return IsolateChannel(receivePort, sendPort); } /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { var controller = - new StreamChannelController(allowForeignErrors: false, sync: true); + StreamChannelController(allowForeignErrors: false, sync: true); receivePort.cast().pipe(controller.local.sink); controller.local.stream .listen((data) => sendPort.send(data), onDone: receivePort.close); - return new IsolateChannel._( - controller.foreign.stream, controller.foreign.sink); + return IsolateChannel._(controller.foreign.stream, controller.foreign.sink); } IsolateChannel._(this.stream, this.sink); diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 6377eeda7e..2a3a86f3e8 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -10,7 +10,7 @@ import '../stream_channel.dart'; import 'stream_channel_transformer.dart'; /// The canonical instance of [JsonDocumentTransformer]. -final jsonDocument = new JsonDocumentTransformer(); +final jsonDocument = JsonDocumentTransformer(); /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. @@ -31,16 +31,16 @@ class JsonDocumentTransformer /// The [reviver] and [toEncodable] arguments work the same way as the /// corresponding arguments to [new JsonCodec]. JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) - : _codec = new JsonCodec(reviver: reviver, toEncodable: toEncodable); + : _codec = JsonCodec(reviver: reviver, toEncodable: toEncodable); JsonDocumentTransformer._(this._codec); StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers( + var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); - return new StreamChannel.withCloseGuarantee(stream, sink); + return StreamChannel.withCloseGuarantee(stream, sink); } } diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a6d684a134..139c9aefa9 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -58,8 +58,7 @@ abstract class MultiChannel implements StreamChannel { /// [inner]. /// /// The inner channel must take JSON-like objects. - factory MultiChannel(StreamChannel inner) => - new _MultiChannel(inner); + factory MultiChannel(StreamChannel inner) => _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -93,7 +92,7 @@ class _MultiChannel extends StreamChannelMixin StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. - final _mainController = new StreamChannelController(sync: true); + final _mainController = StreamChannelController(sync: true); /// A map from input IDs to [StreamChannelController]s that should be used to /// communicate over those channels. @@ -101,11 +100,11 @@ class _MultiChannel extends StreamChannelMixin /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. - final _pendingIds = new Set(); + final _pendingIds = Set(); /// Input IDs of virtual channels that used to exist but have since been /// closed. - final _closedIds = new Set(); + final _closedIds = Set(); /// The next id to use for a local virtual channel. /// @@ -149,7 +148,7 @@ class _MultiChannel extends StreamChannelMixin // counterpart yet, create a controller for it to buffer incoming // messages for when a local connection is created. _pendingIds.add(id); - return new StreamChannelController(sync: true); + return StreamChannelController(sync: true); }); if (message.length > 1) { @@ -187,8 +186,7 @@ class _MultiChannel extends StreamChannelMixin // If the inner channel has already closed, create new virtual channels in a // closed state. if (_inner == null) { - return new VirtualChannel._( - this, inputId, new Stream.empty(), new NullStreamSink()); + return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); } StreamChannelController controller; @@ -198,16 +196,16 @@ class _MultiChannel extends StreamChannelMixin controller = _controllers[inputId]; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { - throw new ArgumentError("A virtual channel with id $id already exists."); + throw ArgumentError("A virtual channel with id $id already exists."); } else { - controller = new StreamChannelController(sync: true); + controller = StreamChannelController(sync: true); _controllers[inputId] = controller; } controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); - return new VirtualChannel._( + return VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); } @@ -234,7 +232,7 @@ class _MultiChannel extends StreamChannelMixin // Convert this to a list because the close is dispatched synchronously, and // that could conceivably remove a controller from [_controllers]. - for (var controller in new List.from(_controllers.values)) { + for (var controller in List.from(_controllers.values)) { controller.local.sink.close(); } _controllers.clear(); diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index b9881b9131..e94eda66ee 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -15,10 +15,10 @@ import '../stream_channel.dart'; /// any events and all events added to it will be buffered. class StreamChannelCompleter { /// The completer for this channel's stream. - final _streamCompleter = new StreamCompleter(); + final _streamCompleter = StreamCompleter(); /// The completer for this channel's sink. - final _sinkCompleter = new StreamSinkCompleter(); + final _sinkCompleter = StreamSinkCompleter(); /// The channel for this completer. StreamChannel get channel => _channel; @@ -36,14 +36,13 @@ class StreamChannelCompleter { /// instead contain just that error. The sink will silently discard all /// events. static StreamChannel fromFuture(Future channelFuture) { - var completer = new StreamChannelCompleter(); + var completer = StreamChannelCompleter(); channelFuture.then(completer.setChannel, onError: completer.setError); return completer.channel; } StreamChannelCompleter() { - _channel = - new StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); + _channel = StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); } /// Set a channel as the source and destination for [channel]. @@ -53,7 +52,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setChannel(StreamChannel channel) { - if (_set) throw new StateError("The channel has already been set."); + if (_set) throw StateError("The channel has already been set."); _set = true; _streamCompleter.setSourceStream(channel.stream); @@ -68,10 +67,10 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setError(error, [StackTrace stackTrace]) { - if (_set) throw new StateError("The channel has already been set."); + if (_set) throw StateError("The channel has already been set."); _set = true; _streamCompleter.setError(error, stackTrace); - _sinkCompleter.setDestinationSink(new NullStreamSink()); + _sinkCompleter.setDestinationSink(NullStreamSink()); } } diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 146e99667f..136886df70 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -52,12 +52,12 @@ class StreamChannelController { /// the foreign channel's sink. If any are, the connection will close and the /// error will be forwarded to the foreign channel's [StreamSink.done] future. /// This guarantees that the local stream will never emit errors. - StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { - var localToForeignController = new StreamController(sync: sync); - var foreignToLocalController = new StreamController(sync: sync); - _local = new StreamChannel.withGuarantees( + StreamChannelController({bool allowForeignErrors = true, bool sync = false}) { + var localToForeignController = StreamController(sync: sync); + var foreignToLocalController = StreamController(sync: sync); + _local = StreamChannel.withGuarantees( foreignToLocalController.stream, localToForeignController.sink); - _foreign = new StreamChannel.withGuarantees( + _foreign = StreamChannel.withGuarantees( localToForeignController.stream, foreignToLocalController.sink, allowSinkErrors: allowForeignErrors); } diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index cc9bad881b..32d36b6b05 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -45,7 +45,7 @@ class StreamChannelTransformer { StreamChannelTransformer transformer) => transformer is StreamChannelTransformer ? transformer - : new TypeSafeStreamChannelTransformer(transformer); + : TypeSafeStreamChannelTransformer(transformer); /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. @@ -58,7 +58,7 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this(codec.decoder, - new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + StreamSinkTransformer.fromStreamTransformer(codec.encoder)); /// Transforms the events sent to and emitted by [channel]. /// @@ -68,7 +68,7 @@ class StreamChannelTransformer { /// `channel.straem`, the transformer will transform them and pass the /// transformed versions to the returned channel's stream. StreamChannel bind(StreamChannel channel) => - new StreamChannel.withCloseGuarantee( + StreamChannel.withCloseGuarantee( channel.stream.transform(_streamTransformer), _sinkTransformer.bind(channel.sink)); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ce3cf04a70..b50116044c 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -72,7 +72,7 @@ abstract class StreamChannel { /// [StreamChannel] documentation. If they don't do so natively, /// [StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => - new _StreamChannel(stream, sink); + _StreamChannel(stream, sink); /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// @@ -85,8 +85,8 @@ abstract class StreamChannel { /// [sink]. If any are, the connection will close and the error will be /// forwarded to [sink].done. factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, - {bool allowSinkErrors: true}) => - new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); + {bool allowSinkErrors = true}) => + GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// @@ -99,7 +99,7 @@ abstract class StreamChannel { /// [StreamChannel.withGuarantees]. factory StreamChannel.withCloseGuarantee( Stream stream, StreamSink sink) => - new CloseGuaranteeChannel(stream, sink); + CloseGuaranteeChannel(stream, sink); /// Connects this to [other], so that any values emitted by either are sent /// directly to the other. @@ -162,11 +162,11 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); StreamChannel changeStream(Stream change(Stream stream)) => - new StreamChannel.withCloseGuarantee(change(stream), sink); + StreamChannel.withCloseGuarantee(change(stream), sink); StreamChannel changeSink(StreamSink change(StreamSink sink)) => - new StreamChannel.withCloseGuarantee(stream, change(sink)); + StreamChannel.withCloseGuarantee(stream, change(sink)); - StreamChannel cast() => new StreamChannel( + StreamChannel cast() => StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 6b1ace36f7..996cd70475 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_channel -version: 1.6.8 +version: 1.6.9 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.0.0-dev.17.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: async: '>=1.11.0 <3.0.0' diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 62ef78b546..7b36c29b61 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -14,10 +14,10 @@ void main() { Disconnector disconnector; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - disconnector = new Disconnector(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + disconnector = Disconnector(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink) .transform(disconnector); }); @@ -47,17 +47,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -67,7 +67,7 @@ void main() { test("cancels addStream when disconnected", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); @@ -78,11 +78,11 @@ void main() { }); test("disconnect() returns the close future from the inner sink", () async { - var streamController = new StreamController(); - var sinkController = new StreamController(); - var disconnector = new Disconnector(); - var sink = new _CloseCompleterSink(sinkController.sink); - new StreamChannel.withGuarantees(streamController.stream, sink) + var streamController = StreamController(); + var sinkController = StreamController(); + var disconnector = Disconnector(); + var sink = _CloseCompleterSink(sinkController.sink); + StreamChannel.withGuarantees(streamController.stream, sink) .transform(disconnector); var disconnectFutureFired = false; @@ -140,7 +140,7 @@ void main() { /// returned by [close] using [completer]. class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. - final completer = new Completer(); + final completer = Completer(); _CloseCompleterSink(StreamSink inner) : super(inner); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 4c73ab090c..8971972b52 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -15,10 +15,10 @@ void main() { SendPort sendPort; StreamChannel channel; setUp(() { - receivePort = new ReceivePort(); - var receivePortForSend = new ReceivePort(); + receivePort = ReceivePort(); + var receivePortForSend = ReceivePort(); sendPort = receivePortForSend.sendPort; - channel = new IsolateChannel(receivePortForSend, receivePort.sendPort); + channel = IsolateChannel(receivePortForSend, receivePort.sendPort); }); tearDown(() { @@ -46,17 +46,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -107,7 +107,7 @@ void main() { test("the sink closes as soon as an error is added via addStream", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); @@ -128,7 +128,7 @@ void main() { group("connect constructors", () { ReceivePort connectPort; setUp(() { - connectPort = new ReceivePort(); + connectPort = ReceivePort(); }); tearDown(() { @@ -136,8 +136,8 @@ void main() { }); test("create a connected pair of channels", () { - var channel1 = new IsolateChannel.connectReceive(connectPort); - var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + var channel1 = IsolateChannel.connectReceive(connectPort); + var channel2 = IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); @@ -152,7 +152,7 @@ void main() { test("the receiving channel produces an error if it gets the wrong message", () { - var connectedChannel = new IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); connectPort.sendPort.send("wrong value"); expect(connectedChannel.stream.toList(), throwsStateError); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 6cb97f9454..83ee099294 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -13,10 +13,10 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = - new StreamChannel(streamController.stream, sinkController.sink); + StreamChannel(streamController.stream, sinkController.sink); }); test("decodes JSON emitted by the channel", () { @@ -33,16 +33,16 @@ void main() { }); test("supports the reviver function", () { - var transformed = channel.transform( - new JsonDocumentTransformer(reviver: (key, value) => "decoded")); + var transformed = channel + .transform(JsonDocumentTransformer(reviver: (key, value) => "decoded")); streamController.add('{"foo": "bar"}'); expect(transformed.stream.first, completion(equals("decoded"))); }); test("supports the toEncodable function", () { - var transformed = channel.transform( - new JsonDocumentTransformer(toEncodable: (object) => "encoded")); - transformed.sink.add(new Object()); + var transformed = channel + .transform(JsonDocumentTransformer(toEncodable: (object) => "encoded")); + transformed.sink.add(Object()); expect(sinkController.stream.first, completion(equals('"encoded"'))); }); @@ -54,7 +54,7 @@ void main() { test("synchronously throws if an unencodable object is added", () { var transformed = channel.transform(jsonDocument); - expect(() => transformed.sink.add(new Object()), - throwsA(new TypeMatcher())); + expect(() => transformed.sink.add(Object()), + throwsA(TypeMatcher())); }); } diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index ddc4150bbc..80c595a395 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -10,9 +10,9 @@ void main() { MultiChannel channel1; MultiChannel channel2; setUp(() { - controller = new StreamChannelController(); - channel1 = new MultiChannel(controller.local); - channel2 = new MultiChannel(controller.foreign); + controller = StreamChannelController(); + channel1 = MultiChannel(controller.local); + channel2 = MultiChannel(controller.foreign); }); group("the default virtual channel", () { diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 666efe9ede..c20f9af111 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -13,11 +13,10 @@ void main() { StreamController sinkController; StreamChannel innerChannel; setUp(() { - completer = new StreamChannelCompleter(); - streamController = new StreamController(); - sinkController = new StreamController(); - innerChannel = - new StreamChannel(streamController.stream, sinkController.sink); + completer = StreamChannelCompleter(); + streamController = StreamController(); + sinkController = StreamController(); + innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); group("when a channel is set before accessing", () { @@ -97,7 +96,7 @@ void main() { group("forFuture", () { test("forwards a StreamChannel", () { var channel = - StreamChannelCompleter.fromFuture(new Future.value(innerChannel)); + StreamChannelCompleter.fromFuture(Future.value(innerChannel)); channel.sink.add(1); channel.sink.close(); streamController.sink.add(2); @@ -108,8 +107,7 @@ void main() { }); test("forwards an error", () { - var channel = - StreamChannelCompleter.fromFuture(new Future.error("oh no")); + var channel = StreamChannelCompleter.fromFuture(Future.error("oh no")); expect(channel.stream.toList(), throwsA("oh no")); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 483b7f6f1f..62f883fa5e 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -9,7 +9,7 @@ void main() { group("asynchronously", () { StreamChannelController controller; setUp(() { - controller = new StreamChannelController(); + controller = StreamChannelController(); }); test("forwards events from the local sink to the foreign stream", () { @@ -33,7 +33,7 @@ void main() { test( "with allowForeignErrors: false, shuts down the connection if an " "error is added to the foreign channel", () { - controller = new StreamChannelController(allowForeignErrors: false); + controller = StreamChannelController(allowForeignErrors: false); controller.foreign.sink.addError("oh no"); expect(controller.foreign.sink.done, throwsA("oh no")); @@ -46,7 +46,7 @@ void main() { group("synchronously", () { StreamChannelController controller; setUp(() { - controller = new StreamChannelController(sync: true); + controller = StreamChannelController(sync: true); }); test( diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index dbe4211956..2f05a9ef11 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -14,17 +14,17 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel(streamController.stream, sinkController.sink); + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel(streamController.stream, sinkController.sink); }); test("pipe() pipes data from each channel's stream into the other's sink", () { - var otherStreamController = new StreamController(); - var otherSinkController = new StreamController(); - var otherChannel = new StreamChannel( - otherStreamController.stream, otherSinkController.sink); + var otherStreamController = StreamController(); + var otherSinkController = StreamController(); + var otherChannel = + StreamChannel(otherStreamController.stream, otherSinkController.sink); channel.pipe(otherChannel); streamController.add(1); @@ -43,7 +43,7 @@ void main() { test("transform() transforms the channel", () async { var transformed = channel .cast>() - .transform(new StreamChannelTransformer.fromCodec(utf8)); + .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); @@ -76,7 +76,7 @@ void main() { test("transformSink() transforms only the sink", () async { var transformed = channel.cast().transformSink( - new StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); + StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); streamController.add("fbl\nthp"); streamController.close(); @@ -91,7 +91,7 @@ void main() { }); test("changeStream() changes the stream", () { - var newController = new StreamController(); + var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); return newController.stream; @@ -107,7 +107,7 @@ void main() { }); test("changeSink() changes the sink", () { - var newController = new StreamController(); + var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); return newController.sink; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 8e1b63119f..1749bacb7a 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -8,18 +8,18 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -final _delayTransformer = new StreamTransformer.fromHandlers( - handleData: (data, sink) => new Future.microtask(() => sink.add(data)), - handleDone: (sink) => new Future.microtask(() => sink.close())); +final _delayTransformer = StreamTransformer.fromHandlers( + handleData: (data, sink) => Future.microtask(() => sink.add(data)), + handleDone: (sink) => Future.microtask(() => sink.close())); final _delaySinkTransformer = - new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); + StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { StreamChannelController controller; StreamChannel channel; setUp(() { - controller = new StreamChannelController(); + controller = StreamChannelController(); // Add a bunch of layers of asynchronous dispatch between the channel and // the underlying controllers. @@ -30,7 +30,7 @@ void main() { sink = _delaySinkTransformer.bind(sink); } - channel = new StreamChannel.withCloseGuarantee(stream, sink); + channel = StreamChannel.withCloseGuarantee(stream, sink); }); test( diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index dcdffe0891..0ea59525e5 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -12,16 +12,16 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); group("with a broadcast stream", () { setUp(() { - streamController = new StreamController.broadcast(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController.broadcast(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); @@ -121,17 +121,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -140,9 +140,9 @@ void main() { group("with allowSinkErrors: false", () { setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink, allowSinkErrors: false); }); @@ -180,7 +180,7 @@ void main() { "adding an error via via addStream causes the stream to emit a done " "event", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); From b86f7a0e74b91682ce3e6889278ea0f7724c4689 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Mar 2019 15:38:48 -0700 Subject: [PATCH 063/138] Add separate import for `IsolateChannel` (dart-lang/stream_channel#40) This will allow us to move to this import in the few packages which are using this class, like test, without having a fully broken state in between, and without required `git` dependency overrides. --- pkgs/stream_channel/CHANGELOG.md | 7 +++++-- pkgs/stream_channel/lib/isolate_channel.dart | 5 +++++ pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_channel/lib/isolate_channel.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 87ba42fe7d..68b68a1123 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,10 @@ -## 1.6.9 +## 1.7.0 +* Make `IsolateChannel` available through + `package:stream_channel/isolate_channel.dart`. This will be the required + import in the next release. * Require `2.0.0` or newer SDK. -* Drop unnecessary `new` and `const`. +* Internal style changes. ## 1.6.8 diff --git a/pkgs/stream_channel/lib/isolate_channel.dart b/pkgs/stream_channel/lib/isolate_channel.dart new file mode 100644 index 0000000000..5d9f6e19f6 --- /dev/null +++ b/pkgs/stream_channel/lib/isolate_channel.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2019, 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. + +export 'src/isolate_channel.dart' show IsolateChannel; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 996cd70475..da152fb399 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.9 +version: 1.7.0 description: An abstraction for two-way communication channels. author: Dart Team diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 8971972b52..776928d720 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; From c3babdc1bac5cabeda1d41b48fda4840d7a84d3d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Mar 2019 09:00:36 -0700 Subject: [PATCH 064/138] Enforce override annotations (dart-lang/stream_channel#42) --- pkgs/stream_channel/analysis_options.yaml | 1 + pkgs/stream_channel/lib/src/close_guarantee_channel.dart | 4 ++++ .../lib/src/delegating_stream_channel.dart | 2 ++ pkgs/stream_channel/lib/src/disconnector.dart | 6 ++++++ pkgs/stream_channel/lib/src/guarantee_channel.dart | 7 +++++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 2 ++ .../lib/src/json_document_transformer.dart | 1 + pkgs/stream_channel/lib/src/multi_channel.dart | 8 ++++++++ pkgs/stream_channel/lib/src/transformer/typed.dart | 1 + pkgs/stream_channel/lib/stream_channel.dart | 9 +++++++++ pkgs/stream_channel/test/disconnector_test.dart | 1 + 11 files changed, 42 insertions(+) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index d19ee843f7..866c1585af 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,5 +8,6 @@ analyzer: linter: rules: + - annotate_overrides - comment_references - prefer_typing_uninitialized_variables diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index b8a3f02890..c534a919ec 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -14,9 +14,11 @@ import '../stream_channel.dart'; /// /// This is exposed via [new StreamChannel.withCloseGuarantee]. class CloseGuaranteeChannel extends StreamChannelMixin { + @override Stream get stream => _stream; _CloseGuaranteeStream _stream; + @override StreamSink get sink => _sink; _CloseGuaranteeSink _sink; @@ -45,6 +47,7 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); + @override StreamSubscription listen(void onData(T event), {Function onError, void onDone(), bool cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything @@ -73,6 +76,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + @override Future close() { var done = super.close(); _channel._disconnected = true; diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart index 4434cf62a0..4484a59897 100644 --- a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -14,7 +14,9 @@ class DelegatingStreamChannel extends StreamChannelMixin { /// The inner channel to which methods are forwarded. final StreamChannel _inner; + @override Stream get stream => _inner.stream; + @override StreamSink get sink => _inner.sink; DelegatingStreamChannel(this._inner); diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 9d35cfc63f..83defb8c38 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -40,6 +40,7 @@ class Disconnector implements StreamChannelTransformer { }); final _disconnectMemo = AsyncMemoizer(); + @override StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { var sink = _DisconnectorSink(innerSink); @@ -62,6 +63,7 @@ class _DisconnectorSink implements StreamSink { /// The inner sink. final StreamSink _inner; + @override Future get done => _inner.done; /// Whether [Disconnector.disconnect] has been called. @@ -83,6 +85,7 @@ class _DisconnectorSink implements StreamSink { _DisconnectorSink(this._inner); + @override void add(T data) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -93,6 +96,7 @@ class _DisconnectorSink implements StreamSink { _inner.add(data); } + @override void addError(error, [StackTrace stackTrace]) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -103,6 +107,7 @@ class _DisconnectorSink implements StreamSink { _inner.addError(error, stackTrace); } + @override Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { @@ -119,6 +124,7 @@ class _DisconnectorSink implements StreamSink { }); } + @override Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index e96f5c3c8a..ce7f70736a 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -12,8 +12,10 @@ import '../stream_channel.dart'; /// /// This is exposed via [new StreamChannel.withGuarantees]. class GuaranteeChannel extends StreamChannelMixin { + @override Stream get stream => _streamController.stream; + @override StreamSink get sink => _sink; _GuaranteeSink _sink; @@ -78,6 +80,7 @@ class _GuaranteeSink implements StreamSink { /// The [GuaranteeChannel] this belongs to. final GuaranteeChannel _channel; + @override Future get done => _doneCompleter.future; final _doneCompleter = Completer(); @@ -110,6 +113,7 @@ class _GuaranteeSink implements StreamSink { _GuaranteeSink(this._inner, this._channel, {bool allowErrors = true}) : _allowErrors = allowErrors; + @override void add(T data) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -120,6 +124,7 @@ class _GuaranteeSink implements StreamSink { _inner.add(data); } + @override void addError(error, [StackTrace stackTrace]) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -151,6 +156,7 @@ class _GuaranteeSink implements StreamSink { _inner.close().catchError((_) {}); } + @override Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { @@ -167,6 +173,7 @@ class _GuaranteeSink implements StreamSink { }); } + @override Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c7f573fd2a..8c1b568420 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -24,7 +24,9 @@ import '../stream_channel.dart'; /// ensure that they always close the [sink] of every [IsolateChannel] they use /// to avoid leaving dangling [ReceivePort]s. class IsolateChannel extends StreamChannelMixin { + @override final Stream stream; + @override final StreamSink sink; /// Connects to a remote channel that was created with diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 2a3a86f3e8..a53ac92ad9 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -35,6 +35,7 @@ class JsonDocumentTransformer JsonDocumentTransformer._(this._codec); + @override StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); var sink = StreamSinkTransformer.fromHandlers( diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 139c9aefa9..d729eb7bbe 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -45,6 +45,7 @@ abstract class MultiChannel implements StreamChannel { /// The default input stream. /// /// This connects to the remote [sink]. + @override Stream get stream; /// The default output stream. @@ -52,6 +53,7 @@ abstract class MultiChannel implements StreamChannel { /// This connects to the remote [stream]. If this is closed, the remote /// [stream] will close, but other virtual channels will remain open and new /// virtual channels may be opened. + @override StreamSink get sink; /// Creates a new [MultiChannel] that sends and receives messages over @@ -88,7 +90,9 @@ class _MultiChannel extends StreamChannelMixin /// The subscription to [_inner].stream. StreamSubscription _innerStreamSubscription; + @override Stream get stream => _mainController.foreign.stream; + @override StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. @@ -165,6 +169,7 @@ class _MultiChannel extends StreamChannelMixin onError: _mainController.local.sink.addError); } + @override VirtualChannel virtualChannel([int id]) { int inputId; int outputId; @@ -256,10 +261,13 @@ class VirtualChannel extends StreamChannelMixin /// except that it will be JSON-serializable. final int id; + @override final Stream stream; + @override final StreamSink sink; VirtualChannel._(this._parent, this.id, this.stream, this.sink); + @override VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart index 9c2d72b41c..875cdac37b 100644 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -12,6 +12,7 @@ class TypeSafeStreamChannelTransformer TypeSafeStreamChannelTransformer(this._inner); + @override StreamChannel bind(StreamChannel channel) => _inner.bind(channel).cast(); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index b50116044c..a5cd5849cf 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -138,7 +138,9 @@ abstract class StreamChannel { /// This is distinct from [StreamChannel] so that it can use /// [StreamChannelMixin]. class _StreamChannel extends StreamChannelMixin { + @override final Stream stream; + @override final StreamSink sink; _StreamChannel(this.stream, this.sink); @@ -147,26 +149,33 @@ class _StreamChannel extends StreamChannelMixin { /// A mixin that implements the instance methods of [StreamChannel] in terms of /// [stream] and [sink]. abstract class StreamChannelMixin implements StreamChannel { + @override void pipe(StreamChannel other) { stream.pipe(other.sink); other.stream.pipe(sink); } + @override StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); + @override StreamChannel transformStream(StreamTransformer transformer) => changeStream(transformer.bind); + @override StreamChannel transformSink(StreamSinkTransformer transformer) => changeSink(transformer.bind); + @override StreamChannel changeStream(Stream change(Stream stream)) => StreamChannel.withCloseGuarantee(change(stream), sink); + @override StreamChannel changeSink(StreamSink change(StreamSink sink)) => StreamChannel.withCloseGuarantee(stream, change(sink)); + @override StreamChannel cast() => StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 7b36c29b61..aefad28d48 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -144,6 +144,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { _CloseCompleterSink(StreamSink inner) : super(inner); + @override Future close() { super.close(); return completer.future; From db09351495a71df5445a627a8b01bd3af23f8073 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Mar 2019 17:26:19 -0700 Subject: [PATCH 065/138] Move isolate_channel to it's own import (dart-lang/stream_channel#39) Closes dart-lang/stream_channel#36 This allows the default import to work without triggering any warnings on the web due to transitively importing `dart:isolate`. This is required to allow restricting imports based on platform. --- pkgs/stream_channel/CHANGELOG.md | 7 +++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 - pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 68b68a1123..0e125ddae8 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,10 @@ +## 2.0.0 + +* **Breaking change** `IsolateChannel` requires a separate import + `package:stram_channel/isolate_channel.dart`. + `package:stream_channel/stream_channel.dart` will now not trigger any platform + concerns due to importing `dart:isolate`. + ## 1.7.0 * Make `IsolateChannel` available through diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index a5cd5849cf..e99de08f09 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -12,7 +12,6 @@ import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/disconnector.dart'; -export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index da152fb399..917f5bc380 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.7.0 +version: 2.0.0 description: An abstraction for two-way communication channels. author: Dart Team From 662bcb457877736852df2640998d22cdea7ce9f6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 08:26:01 -0700 Subject: [PATCH 066/138] Hide JsonDocumentTransformer (dart-lang/stream_channel#43) Closes dart-lang/stream_channel#34 This was only used through the top level variable `jsonDocument` and no use cases have surfaced for being able to pass a `reviver` or `toEncodable` callback. This implementation does not use `StreamChannelTransformer.fromCodec` with a `JsonCodec` since the encoder and decoder are not 1:1. - Remove the `JsonCodec` field and use `jsonEncode` and `jsonDecode` calls directly. - Move the detailed doc to `jsonDocument`. - Make the class private. - Remove the tests constructing the class directly. --- pkgs/stream_channel/CHANGELOG.md | 6 ++++- .../lib/src/json_document_transformer.dart | 23 +++++-------------- .../test/json_document_transformer_test.dart | 14 ----------- 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0e125ddae8..8ebdc28749 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,9 +1,13 @@ ## 2.0.0 -* **Breaking change** `IsolateChannel` requires a separate import +**Breaking changes** + +* `IsolateChannel` requires a separate import `package:stram_channel/isolate_channel.dart`. `package:stream_channel/stream_channel.dart` will now not trigger any platform concerns due to importing `dart:isolate`. +* Remove `JsonDocumentTransformer` class. The `jsonDocument` top level is still + available. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index a53ac92ad9..8bffc8ab93 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -9,9 +9,6 @@ import 'package:async/async.dart'; import '../stream_channel.dart'; import 'stream_channel_transformer.dart'; -/// The canonical instance of [JsonDocumentTransformer]. -final jsonDocument = JsonDocumentTransformer(); - /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. /// @@ -21,26 +18,18 @@ final jsonDocument = JsonDocumentTransformer(); /// If the transformed channel emits invalid JSON, this emits a /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. -class JsonDocumentTransformer - implements StreamChannelTransformer { - /// The underlying codec that implements the encoding and decoding logic. - final JsonCodec _codec; - - /// Creates a new transformer. - /// - /// The [reviver] and [toEncodable] arguments work the same way as the - /// corresponding arguments to [new JsonCodec]. - JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) - : _codec = JsonCodec(reviver: reviver, toEncodable: toEncodable); +final StreamChannelTransformer jsonDocument = + const _JsonDocument(); - JsonDocumentTransformer._(this._codec); +class _JsonDocument implements StreamChannelTransformer { + const _JsonDocument(); @override StreamChannel bind(StreamChannel channel) { - var stream = channel.stream.map(_codec.decode); + var stream = channel.stream.map(jsonDecode); var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { - sink.add(_codec.encode(data)); + sink.add(jsonEncode(data)); }).bind(channel.sink); return StreamChannel.withCloseGuarantee(stream, sink); } diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 83ee099294..e6c560aded 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -32,20 +32,6 @@ void main() { completion(equals(jsonEncode({"foo": "bar"})))); }); - test("supports the reviver function", () { - var transformed = channel - .transform(JsonDocumentTransformer(reviver: (key, value) => "decoded")); - streamController.add('{"foo": "bar"}'); - expect(transformed.stream.first, completion(equals("decoded"))); - }); - - test("supports the toEncodable function", () { - var transformed = channel - .transform(JsonDocumentTransformer(toEncodable: (object) => "encoded")); - transformed.sink.add(Object()); - expect(sinkController.stream.first, completion(equals('"encoded"'))); - }); - test("emits a stream error when incoming JSON is malformed", () { var transformed = channel.transform(jsonDocument); streamController.add("{invalid"); From 7c910babe483446f0641fbb398fce4abf66e56e0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 09:48:58 -0700 Subject: [PATCH 067/138] Remove StreamChannelTransformer.typed (dart-lang/stream_channel#44) Closes dart-lang/stream_channel#41 I cannot find any uses of this and it can be replaced with a call to `cast`. --- pkgs/stream_channel/CHANGELOG.md | 2 ++ .../lib/src/stream_channel_transformer.dart | 16 ---------------- .../lib/src/transformer/typed.dart | 18 ------------------ 3 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 pkgs/stream_channel/lib/src/transformer/typed.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8ebdc28749..60400e0dfd 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -8,6 +8,8 @@ concerns due to importing `dart:isolate`. * Remove `JsonDocumentTransformer` class. The `jsonDocument` top level is still available. +* Remove `StreamChannelTransformer.typed`. Use `.cast` on the transformed + channel instead. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 32d36b6b05..cf62c76c27 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -8,7 +8,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'transformer/typed.dart'; /// A [StreamChannelTransformer] transforms the events being passed to and /// emitted by a [StreamChannel]. @@ -32,21 +31,6 @@ class StreamChannelTransformer { /// The transformer to use on the channel's sink. final StreamSinkTransformer _sinkTransformer; - /// Creates a wrapper that coerces the type of [transformer]. - /// - /// This soundly converts a [StreamChannelTransformer] to a - /// `StreamChannelTransformer`, regardless of its original generic type, - /// by asserting that the events emitted by the transformed channel's stream - /// are instances of `T` whenever they're provided. If they're not, the stream - /// throws a [CastError]. This also means that calls to [StreamSink.add] on - /// the transformed channel's sink may throw a [CastError] if the argument - /// type doesn't match the reified type of the sink. - static StreamChannelTransformer typed( - StreamChannelTransformer transformer) => - transformer is StreamChannelTransformer - ? transformer - : TypeSafeStreamChannelTransformer(transformer); - /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. const StreamChannelTransformer( diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart deleted file mode 100644 index 875cdac37b..0000000000 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2016, 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 '../../stream_channel.dart'; - -/// A wrapper that coerces the generic type of the channel returned by an inner -/// transformer to `S`. -class TypeSafeStreamChannelTransformer - implements StreamChannelTransformer { - final StreamChannelTransformer _inner; - - TypeSafeStreamChannelTransformer(this._inner); - - @override - StreamChannel bind(StreamChannel channel) => - _inner.bind(channel).cast(); -} From e4af414323baea76d971da80e8a48748d3983467 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 11:06:27 -0700 Subject: [PATCH 068/138] Change all bare Future to Future (dart-lang/stream_channel#45) Closes dart-lang/stream_channel#35 It looks less like a potential bug and more explicitly expresses that these functions don't return useful values. --- pkgs/stream_channel/CHANGELOG.md | 1 + .../lib/src/close_guarantee_channel.dart | 2 +- pkgs/stream_channel/lib/src/disconnector.dart | 10 +++++----- pkgs/stream_channel/lib/src/guarantee_channel.dart | 6 +++--- pkgs/stream_channel/test/disconnector_test.dart | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 60400e0dfd..24564ede10 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -10,6 +10,7 @@ available. * Remove `StreamChannelTransformer.typed`. Use `.cast` on the transformed channel instead. +* Change `Future` returns to `Future`. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index c534a919ec..33296da433 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -77,7 +77,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); @override - Future close() { + Future close() { var done = super.close(); _channel._disconnected = true; if (_channel._subscription != null) { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 83defb8c38..69fbab727c 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -33,7 +33,7 @@ class Disconnector implements StreamChannelTransformer { /// Returns a future that completes when all inner sinks' [StreamSink.close] /// futures have completed. Note that a [StreamController]'s sink won't close /// until the corresponding stream has a listener. - Future disconnect() => _disconnectMemo.runOnce(() { + Future disconnect() => _disconnectMemo.runOnce(() { var futures = _sinks.map((sink) => sink._disconnect()).toList(); _sinks.clear(); return Future.wait(futures, eagerError: true); @@ -64,7 +64,7 @@ class _DisconnectorSink implements StreamSink { final StreamSink _inner; @override - Future get done => _inner.done; + Future get done => _inner.done; /// Whether [Disconnector.disconnect] has been called. var _isDisconnected = false; @@ -108,7 +108,7 @@ class _DisconnectorSink implements StreamSink { } @override - Future addStream(Stream stream) { + Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { throw StateError("Cannot add stream while adding stream."); @@ -125,7 +125,7 @@ class _DisconnectorSink implements StreamSink { } @override - Future close() { + Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); } @@ -138,7 +138,7 @@ class _DisconnectorSink implements StreamSink { /// /// This closes the underlying sink and stops forwarding events. It returns /// the [StreamSink.close] future for the underlying sink. - Future _disconnect() { + Future _disconnect() { _isDisconnected = true; var future = _inner.close(); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index ce7f70736a..d8add39e8c 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -81,7 +81,7 @@ class _GuaranteeSink implements StreamSink { final GuaranteeChannel _channel; @override - Future get done => _doneCompleter.future; + Future get done => _doneCompleter.future; final _doneCompleter = Completer(); /// Whether connection is disconnected. @@ -157,7 +157,7 @@ class _GuaranteeSink implements StreamSink { } @override - Future addStream(Stream stream) { + Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { throw StateError("Cannot add stream while adding stream."); @@ -174,7 +174,7 @@ class _GuaranteeSink implements StreamSink { } @override - Future close() { + Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); } diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index aefad28d48..0992b36343 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -145,7 +145,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { _CloseCompleterSink(StreamSink inner) : super(inner); @override - Future close() { + Future close() { super.close(); return completer.future; } From 56ef31eb7647a35d69332249d2051c60a73798c1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 23 Jul 2019 12:41:26 -0700 Subject: [PATCH 069/138] Use pedantic lints --- pkgs/stream_channel/analysis_options.yaml | 1 + pkgs/stream_channel/pubspec.yaml | 3 +- .../test/disconnector_test.dart | 3 +- .../test/isolate_channel_test.dart | 3 +- .../test/multi_channel_test.dart | 43 ++++++++++--------- .../test/stream_channel_completer_test.dart | 5 ++- .../test/stream_channel_test.dart | 13 +++--- .../test/with_close_guarantee_test.dart | 5 ++- .../test/with_guarantees_test.dart | 17 ++++---- 9 files changed, 51 insertions(+), 42 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 866c1585af..1e02731d75 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: # These are errors when building in Google errors: diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 917f5bc380..dfd3af83da 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.0.0 +version: 2.0.1-dev description: An abstraction for two-way communication channels. author: Dart Team @@ -12,4 +12,5 @@ dependencies: async: '>=1.11.0 <3.0.0' dev_dependencies: + pedantic: ^1.8.0 test: ^1.2.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 0992b36343..a5ea2ebb54 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -71,7 +72,7 @@ void main() { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); - disconnector.disconnect(); + unawaited(disconnector.disconnect()); await pumpEventQueue(); expect(canceled, isTrue); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 776928d720..fd14b8407b 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -82,7 +83,7 @@ void main() { test("cancelling the stream's subscription has no effect on the sink", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); channel.sink.add(1); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 80c595a395..b1659a03a0 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -2,6 +2,7 @@ // 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 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -143,13 +144,13 @@ void main() { "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. - channel1.sink.close(); + unawaited(channel1.sink.close()); await channel2.stream.toList(); expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); }); test( @@ -243,13 +244,13 @@ void main() { "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. - channel2.sink.close(); + unawaited(channel2.sink.close()); await channel1.stream.toList(); expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); }); test( @@ -287,7 +288,7 @@ void main() { "created", () async { virtual1 = channel1.virtualChannel(); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); await pumpEventQueue(); expect(channel2.virtualChannel(virtual1.id).stream.toList(), @@ -317,8 +318,8 @@ void main() { }); test("closes, more virtual channels are created closed", () async { - channel2.sink.close(); - virtual2.sink.close(); + unawaited(channel2.sink.close()); + unawaited(virtual2.sink.close()); // Wait for the existing channels to emit done events. await channel1.stream.toList(); @@ -359,14 +360,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - channel1.sink.close(); + unawaited(channel1.sink.close()); // Wait for the done event to be delivered. await channel2.stream.toList(); channel2.sink.add(1); channel2.sink.add(2); channel2.sink.add(3); - channel2.sink.close(); + unawaited(channel2.sink.close()); // None of our channel.sink additions should make it to the other endpoint. channel1.stream.listen(expectAsync1((_) {}, count: 0)); @@ -375,28 +376,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - channel1.stream.listen(null).cancel(); + unawaited(channel1.stream.listen(null).cancel()); await pumpEventQueue(); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - channel1.sink.close(); + unawaited(channel1.sink.close()); expect(channel2.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - channel1.stream.listen(null).cancel(); + unawaited(channel1.stream.listen(null).cancel()); await pumpEventQueue(); - channel2.sink.close(); + unawaited(channel2.sink.close()); await pumpEventQueue(); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - channel1.sink.close(); + unawaited(channel1.sink.close()); // The sink should be ignoring events because the channel closed. channel2.stream.listen(expectAsync1((_) {}, count: 0)); @@ -426,14 +427,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - virtual1.sink.close(); + unawaited(virtual1.sink.close()); // Wait for the done event to be delivered. await virtual2.stream.toList(); virtual2.sink.add(1); virtual2.sink.add(2); virtual2.sink.add(3); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); // None of our virtual.sink additions should make it to the other endpoint. virtual1.stream.listen(expectAsync1((_) {}, count: 0)); @@ -442,28 +443,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - virtual1.stream.listen(null).cancel(); + unawaited(virtual1.stream.listen(null).cancel()); await pumpEventQueue(); virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); expect(virtual2.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - virtual1.stream.listen(null).cancel(); + unawaited(virtual1.stream.listen(null).cancel()); await pumpEventQueue(); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); await pumpEventQueue(); virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); // The sink should be ignoring events because the stream closed. virtual2.stream.listen(expectAsync1((_) {}, count: 0)); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index c20f9af111..070035e7ba 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -62,14 +63,14 @@ void main() { streamController.add(1); streamController.add(2); streamController.add(3); - streamController.close(); + unawaited(streamController.close()); }); test("forwards events through the sink", () async { completer.channel.sink.add(1); completer.channel.sink.add(2); completer.channel.sink.add(3); - completer.channel.sink.close(); + unawaited(completer.channel.sink.close()); await pumpEventQueue(); completer.setChannel(innerChannel); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 2f05a9ef11..3f4e896b34 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -46,11 +47,11 @@ void main() { .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect( sinkController.stream.toList(), completion(equals([ @@ -65,12 +66,12 @@ void main() { streamController.add("hello world"); streamController.add(" what\nis"); streamController.add("\nup"); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["hello world what", "is", "up"])); transformed.sink.add("fbl\nthp"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); }); @@ -79,13 +80,13 @@ void main() { StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); streamController.add("fbl\nthp"); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["fbl\nthp"])); transformed.sink.add("hello world"); transformed.sink.add(" what\nis"); transformed.sink.add("\nup"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), completion(equals(["hello world what", "is", "up"]))); }); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 1749bacb7a..803dc61f14 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -54,7 +55,7 @@ void main() { test( "closing the event sink before events are emitted causes the stream to " "close immediately", () async { - channel.sink.close(); + unawaited(channel.sink.close()); channel.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync2((_, __) {}, count: 0), onDone: expectAsync0(() {})); @@ -62,7 +63,7 @@ void main() { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); - controller.local.sink.close(); + unawaited(controller.local.sink.close()); await pumpEventQueue(); }); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 0ea59525e5..c9ff59f1e2 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -32,7 +33,7 @@ void main() { await pumpEventQueue(); expect(channel.stream.toList(), completion(equals([1, 2, 3]))); - streamController.close(); + unawaited(streamController.close()); }); test("only allows a single subscription", () { @@ -58,14 +59,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - streamController.close(); + unawaited(streamController.close()); // Wait for the done event to be delivered. await channel.stream.toList(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); // None of our channel.sink additions should make it to the other endpoint. sinkController.stream.listen(expectAsync1((_) {}, count: 0), @@ -75,28 +76,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); - streamController.close(); + unawaited(streamController.close()); await pumpEventQueue(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); // The sink should be ignoring events because the stream closed. sinkController.stream.listen(expectAsync1((_) {}, count: 0), From 33592843725d99b811c25f942de1edf76c5a69a0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:10 -0700 Subject: [PATCH 070/138] Remove unneeded codereview.settings --- pkgs/stream_channel/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stream_channel/codereview.settings diff --git a/pkgs/stream_channel/codereview.settings b/pkgs/stream_channel/codereview.settings deleted file mode 100644 index 7b0a9edc6c..0000000000 --- a/pkgs/stream_channel/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: https://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/stream_channel/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From d77f04738c492f95aca41c991c454f99d36bdafc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:23 -0700 Subject: [PATCH 071/138] Fix outdated URLs --- pkgs/stream_channel/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index 5d6a2b4e04..2ec970b8ef 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -7,10 +7,10 @@ protocol. For example, the [`test`][test] package re-uses its test suite communication protocol for both WebSocket connections to browser suites and Isolate connections to VM tests. -[test]: https://pub.dartlang.org/packages/test +[test]: https://pub.dev/packages/test This package also contains utilities for dealing with `StreamChannel`s and with two-way communications in general. For documentation of these utilities, see [the API docs][api]. -[api]: https://www.dartdocs.org/documentation/stream_channel/latest +[api]: https://pub.dev/documentation/stream_channel/latest/ From 077574a8b132d7f9a2199dc9bbbdcb5a23b940f9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:34 -0700 Subject: [PATCH 072/138] Add missing dartfmt --fix lint --- pkgs/stream_channel/analysis_options.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 1e02731d75..df4128a173 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -11,4 +11,5 @@ linter: rules: - annotate_overrides - comment_references + - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables From 4d81dead936cf59e79334fbc02b404f8f8959edd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:55 -0700 Subject: [PATCH 073/138] Test on oldest supported Dart SDK --- pkgs/stream_channel/.travis.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 45359fb404..69f24c3fa7 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,12 +1,23 @@ language: dart dart: - - dev +- 2.0.0 +- dev + dart_task: - - test: --platform vm - - test: --platform firefox -j 1 - - dartfmt - - dartanalyzer +- test: --platform vm,chrome + +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: + dartanalyzer: --fatal-infos --fatal-warnings . + - dart: 2.0.0 + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: @@ -14,4 +25,4 @@ branches: cache: directories: - - $HOME/.pub-cache + - $HOME/.pub-cache From a3da73812869c4e593b57eb6d04967dee16a949a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:56:05 -0700 Subject: [PATCH 074/138] pubspec: Make the description a bit longer --- pkgs/stream_channel/pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index dfd3af83da..bef50e1cb9 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,7 +1,9 @@ name: stream_channel version: 2.0.1-dev -description: An abstraction for two-way communication channels. +description: >- + An abstraction for two-way communication channels based on the Dart Stream + class. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From f1838d9b911a1865eb92c3c968f6d541e24c6fbe Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 10:14:41 -0700 Subject: [PATCH 075/138] =?UTF-8?q?Require=20Dart=202.2=20=E2=80=93=C2=A0b?= =?UTF-8?q?ecause=20pkg:pedantic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/stream_channel/.travis.yml | 4 ++-- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 69f24c3fa7..d6a5454960 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- 2.0.0 +- 2.2.0 - dev dart_task: @@ -15,7 +15,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.0.0 + - dart: 2.2.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 24564ede10..4f345106a3 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Require Dart `2.2.0` or later. + ## 2.0.0 **Breaking changes** diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bef50e1cb9..61e78c0f3d 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.0.1-dev +version: 2.1.0-dev description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,7 +8,7 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.2.0 <3.0.0' dependencies: async: '>=1.11.0 <3.0.0' From 69ec2c61ec9cf38c57bb41756f9a34d2065c9fcc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Dec 2019 12:45:27 -0800 Subject: [PATCH 076/138] Fix newly enforce package:pedantic lints (dart-lang/stream_channel#48) - use_function_type_syntax_for_parameters - prefer_single_quotes --- .../lib/src/close_guarantee_channel.dart | 4 +- pkgs/stream_channel/lib/src/disconnector.dart | 14 ++-- .../lib/src/guarantee_channel.dart | 14 ++-- .../stream_channel/lib/src/multi_channel.dart | 6 +- .../lib/src/stream_channel_completer.dart | 4 +- pkgs/stream_channel/lib/stream_channel.dart | 8 +- .../test/disconnector_test.dart | 26 +++--- .../test/isolate_channel_test.dart | 34 ++++---- .../test/json_document_transformer_test.dart | 16 ++-- .../test/multi_channel_test.dart | 84 +++++++++---------- .../test/stream_channel_completer_test.dart | 46 +++++----- .../test/stream_channel_controller_test.dart | 32 +++---- .../test/stream_channel_test.dart | 38 ++++----- .../test/with_close_guarantee_test.dart | 8 +- .../test/with_guarantees_test.dart | 52 ++++++------ 15 files changed, 193 insertions(+), 193 deletions(-) diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 33296da433..60916d002e 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -48,8 +48,8 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); @override - StreamSubscription listen(void onData(T event), - {Function onError, void onDone(), bool cancelOnError}) { + StreamSubscription listen(void Function(T) onData, + {Function onError, void Function() onDone, bool cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything // but a done event. if (_channel._disconnected) { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 69fbab727c..e8835374f3 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -87,9 +87,9 @@ class _DisconnectorSink implements StreamSink { @override void add(T data) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_isDisconnected) return; @@ -98,9 +98,9 @@ class _DisconnectorSink implements StreamSink { @override void addError(error, [StackTrace stackTrace]) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_isDisconnected) return; @@ -109,9 +109,9 @@ class _DisconnectorSink implements StreamSink { @override Future addStream(Stream stream) { - if (_closed) throw StateError("Cannot add stream after closing."); + if (_closed) throw StateError('Cannot add stream after closing.'); if (_inAddStream) { - throw StateError("Cannot add stream while adding stream."); + throw StateError('Cannot add stream while adding stream.'); } if (_isDisconnected) return Future.value(); @@ -127,7 +127,7 @@ class _DisconnectorSink implements StreamSink { @override Future close() { if (_inAddStream) { - throw StateError("Cannot close sink while adding stream."); + throw StateError('Cannot close sink while adding stream.'); } _closed = true; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index d8add39e8c..cfee99ee5a 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -115,9 +115,9 @@ class _GuaranteeSink implements StreamSink { @override void add(T data) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_disconnected) return; @@ -126,9 +126,9 @@ class _GuaranteeSink implements StreamSink { @override void addError(error, [StackTrace stackTrace]) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_disconnected) return; @@ -158,9 +158,9 @@ class _GuaranteeSink implements StreamSink { @override Future addStream(Stream stream) { - if (_closed) throw StateError("Cannot add stream after closing."); + if (_closed) throw StateError('Cannot add stream after closing.'); if (_inAddStream) { - throw StateError("Cannot add stream while adding stream."); + throw StateError('Cannot add stream while adding stream.'); } if (_disconnected) return Future.value(); @@ -176,7 +176,7 @@ class _GuaranteeSink implements StreamSink { @override Future close() { if (_inAddStream) { - throw StateError("Cannot close sink while adding stream."); + throw StateError('Cannot close sink while adding stream.'); } if (_closed) return done; diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index d729eb7bbe..e0982ae19b 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -104,11 +104,11 @@ class _MultiChannel extends StreamChannelMixin /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. - final _pendingIds = Set(); + final _pendingIds = {}; /// Input IDs of virtual channels that used to exist but have since been /// closed. - final _closedIds = Set(); + final _closedIds = {}; /// The next id to use for a local virtual channel. /// @@ -201,7 +201,7 @@ class _MultiChannel extends StreamChannelMixin controller = _controllers[inputId]; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { - throw ArgumentError("A virtual channel with id $id already exists."); + throw ArgumentError('A virtual channel with id $id already exists.'); } else { controller = StreamChannelController(sync: true); _controllers[inputId] = controller; diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index e94eda66ee..a14ffde44a 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -52,7 +52,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setChannel(StreamChannel channel) { - if (_set) throw StateError("The channel has already been set."); + if (_set) throw StateError('The channel has already been set.'); _set = true; _streamCompleter.setSourceStream(channel.stream); @@ -67,7 +67,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setError(error, [StackTrace stackTrace]) { - if (_set) throw StateError("The channel has already been set."); + if (_set) throw StateError('The channel has already been set.'); _set = true; _streamCompleter.setError(error, stackTrace); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index e99de08f09..c806ec663b 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -117,11 +117,11 @@ abstract class StreamChannel { /// Returns a copy of this with [stream] replaced by [change]'s return /// value. - StreamChannel changeStream(Stream change(Stream stream)); + StreamChannel changeStream(Stream Function(Stream) change); /// Returns a copy of this with [sink] replaced by [change]'s return /// value. - StreamChannel changeSink(StreamSink change(StreamSink sink)); + StreamChannel changeSink(StreamSink Function(StreamSink) change); /// Returns a copy of this with the generic type coerced to [S]. /// @@ -167,11 +167,11 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); @override - StreamChannel changeStream(Stream change(Stream stream)) => + StreamChannel changeStream(Stream Function(Stream) change) => StreamChannel.withCloseGuarantee(change(stream), sink); @override - StreamChannel changeSink(StreamSink change(StreamSink sink)) => + StreamChannel changeSink(StreamSink Function(StreamSink) change) => StreamChannel.withCloseGuarantee(stream, change(sink)); @override diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index a5ea2ebb54..ec0c64bc06 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -23,8 +23,8 @@ void main() { .transform(disconnector); }); - group("before disconnection", () { - test("forwards events from the sink as normal", () { + group('before disconnection', () { + test('forwards events from the sink as normal', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -33,7 +33,7 @@ void main() { expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards events to the stream as normal", () { + test('forwards events to the stream as normal', () { streamController.add(1); streamController.add(2); streamController.add(3); @@ -47,7 +47,7 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -57,7 +57,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -66,7 +66,7 @@ void main() { }); }); - test("cancels addStream when disconnected", () async { + test('cancels addStream when disconnected', () async { var canceled = false; var controller = StreamController(onCancel: () { canceled = true; @@ -78,7 +78,7 @@ void main() { expect(canceled, isTrue); }); - test("disconnect() returns the close future from the inner sink", () async { + test('disconnect() returns the close future from the inner sink', () async { var streamController = StreamController(); var sinkController = StreamController(); var disconnector = Disconnector(); @@ -104,12 +104,12 @@ void main() { expect(disconnectFutureFired, isTrue); }); - group("after disconnection", () { + group('after disconnection', () { setUp(() { disconnector.disconnect(); }); - test("closes the inner sink and ignores events to the outer sink", () { + test('closes the inner sink and ignores events to the outer sink', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -118,21 +118,21 @@ void main() { expect(sinkController.stream.toList(), completion(isEmpty)); }); - test("closes the stream", () { + test('closes the stream', () { expect(channel.stream.toList(), completion(isEmpty)); }); - test("completes done", () { + test('completes done', () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.done, completes); }); - test("still emits state errors after explicit close", () { + test('still emits state errors after explicit close', () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); }); }); } diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index fd14b8407b..ab70f749b2 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -28,7 +28,7 @@ void main() { channel.sink.close(); }); - test("the channel can send messages", () { + test('the channel can send messages', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -36,7 +36,7 @@ void main() { expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); }); - test("the channel can receive messages", () { + test('the channel can receive messages', () { sendPort.send(1); sendPort.send(2); sendPort.send(3); @@ -47,7 +47,7 @@ void main() { test("events can't be added to an explicitly-closed sink", () { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -57,7 +57,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -65,10 +65,10 @@ void main() { controller.close(); }); - group("stream channel rules", () { + group('stream channel rules', () { test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { sendPort.send(1); sendPort.send(2); sendPort.send(3); @@ -92,10 +92,10 @@ void main() { expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); }); - test("the sink closes as soon as an error is added", () async { - channel.sink.addError("oh no"); + test('the sink closes as soon as an error is added', () async { + channel.sink.addError('oh no'); channel.sink.add(1); - expect(channel.sink.done, throwsA("oh no")); + expect(channel.sink.done, throwsA('oh no')); // Since the sink is closed, the stream should also be closed. expect(channel.stream.isEmpty, completion(isTrue)); @@ -106,7 +106,7 @@ void main() { await pumpEventQueue(); }); - test("the sink closes as soon as an error is added via addStream", + test('the sink closes as soon as an error is added via addStream', () async { var canceled = false; var controller = StreamController(onCancel: () { @@ -116,8 +116,8 @@ void main() { // This future shouldn't get the error, because it's sent to [Sink.done]. expect(channel.sink.addStream(controller.stream), completes); - controller.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + controller.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); await pumpEventQueue(); expect(canceled, isTrue); @@ -127,7 +127,7 @@ void main() { }); }); - group("connect constructors", () { + group('connect constructors', () { ReceivePort connectPort; setUp(() { connectPort = ReceivePort(); @@ -137,7 +137,7 @@ void main() { connectPort.close(); }); - test("create a connected pair of channels", () { + test('create a connected pair of channels', () { var channel1 = IsolateChannel.connectReceive(connectPort); var channel2 = IsolateChannel.connectSend(connectPort.sendPort); @@ -152,10 +152,10 @@ void main() { expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); }); - test("the receiving channel produces an error if it gets the wrong message", + test('the receiving channel produces an error if it gets the wrong message', () { var connectedChannel = IsolateChannel.connectReceive(connectPort); - connectPort.sendPort.send("wrong value"); + connectPort.sendPort.send('wrong value'); expect(connectedChannel.stream.toList(), throwsStateError); expect(connectedChannel.sink.done, completes); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index e6c560aded..3ccce4ead5 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -19,26 +19,26 @@ void main() { StreamChannel(streamController.stream, sinkController.sink); }); - test("decodes JSON emitted by the channel", () { + test('decodes JSON emitted by the channel', () { var transformed = channel.transform(jsonDocument); streamController.add('{"foo": "bar"}'); - expect(transformed.stream.first, completion(equals({"foo": "bar"}))); + expect(transformed.stream.first, completion(equals({'foo': 'bar'}))); }); - test("encodes objects added to the channel", () { + test('encodes objects added to the channel', () { var transformed = channel.transform(jsonDocument); - transformed.sink.add({"foo": "bar"}); + transformed.sink.add({'foo': 'bar'}); expect(sinkController.stream.first, - completion(equals(jsonEncode({"foo": "bar"})))); + completion(equals(jsonEncode({'foo': 'bar'})))); }); - test("emits a stream error when incoming JSON is malformed", () { + test('emits a stream error when incoming JSON is malformed', () { var transformed = channel.transform(jsonDocument); - streamController.add("{invalid"); + streamController.add('{invalid'); expect(transformed.stream.first, throwsFormatException); }); - test("synchronously throws if an unencodable object is added", () { + test('synchronously throws if an unencodable object is added', () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(Object()), throwsA(TypeMatcher())); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index b1659a03a0..0fa1df9ea9 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -16,8 +16,8 @@ void main() { channel2 = MultiChannel(controller.foreign); }); - group("the default virtual channel", () { - test("begins connected", () { + group('the default virtual channel', () { + test('begins connected', () { var first = true; channel2.stream.listen(expectAsync1((message) { if (first) { @@ -32,14 +32,14 @@ void main() { channel1.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(channel2.stream.toList(), completion(isEmpty)); expect(channel2.sink.done, completes); channel1.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(channel1.stream.toList(), completion(isEmpty)); expect(channel1.sink.done, completes); @@ -48,7 +48,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { channel1.sink.done.then(expectAsync1((_) {}, count: 0)); channel1.stream.listen((_) {}).cancel(); @@ -59,8 +59,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () { expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); @@ -69,7 +69,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -84,7 +84,7 @@ void main() { }); }); - group("a locally-created virtual channel", () { + group('a locally-created virtual channel', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -92,7 +92,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("sends messages only to the other virtual channel", () { + test('sends messages only to the other virtual channel', () { var first = true; virtual2.stream.listen(expectAsync1((message) { if (first) { @@ -114,14 +114,14 @@ void main() { virtual1.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); virtual1.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(virtual1.stream.toList(), completion(isEmpty)); expect(virtual1.sink.done, completes); @@ -130,7 +130,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { virtual1.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); @@ -140,8 +140,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () async { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () async { // First close the default channel so we can test the new channel as the // last living virtual channel. unawaited(channel1.sink.close()); @@ -155,7 +155,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -184,7 +184,7 @@ void main() { }); }); - group("a remotely-created virtual channel", () { + group('a remotely-created virtual channel', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -192,7 +192,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("sends messages only to the other virtual channel", () { + test('sends messages only to the other virtual channel', () { var first = true; virtual1.stream.listen(expectAsync1((message) { if (first) { @@ -214,14 +214,14 @@ void main() { virtual2.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(virtual1.stream.toList(), completion(isEmpty)); expect(virtual1.sink.done, completes); virtual2.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); @@ -230,7 +230,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { virtual2.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); @@ -240,8 +240,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () async { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () async { // First close the default channel so we can test the new channel as the // last living virtual channel. unawaited(channel2.sink.close()); @@ -255,7 +255,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -270,7 +270,7 @@ void main() { expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); - test("dispatches events received before the virtual channel is created", + test('dispatches events received before the virtual channel is created', () async { virtual1 = channel1.virtualChannel(); @@ -284,8 +284,8 @@ void main() { }); test( - "dispatches close events received before the virtual channel is " - "created", () async { + 'dispatches close events received before the virtual channel is ' + 'created', () async { virtual1 = channel1.virtualChannel(); unawaited(virtual1.sink.close()); @@ -296,7 +296,7 @@ void main() { }); }); - group("when the underlying stream", () { + group('when the underlying stream', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -304,7 +304,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("closes, all virtual channels close", () { + test('closes, all virtual channels close', () { expect(channel1.stream.toList(), completion(isEmpty)); expect(channel1.sink.done, completes); expect(channel2.stream.toList(), completion(isEmpty)); @@ -317,7 +317,7 @@ void main() { controller.local.sink.close(); }); - test("closes, more virtual channels are created closed", () async { + test('closes, more virtual channels are created closed', () async { unawaited(channel2.sink.close()); unawaited(virtual2.sink.close()); @@ -334,21 +334,21 @@ void main() { expect(virtual.sink.done, completes); }); - test("emits an error, the error is sent only to the default channel", () { + test('emits an error, the error is sent only to the default channel', () { channel1.stream.listen(expectAsync1((_) {}, count: 0), - onError: expectAsync1((error) => expect(error, equals("oh no")))); + onError: expectAsync1((error) => expect(error, equals('oh no')))); virtual1.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync1((_) {}, count: 0)); - controller.foreign.sink.addError("oh no"); + controller.foreign.sink.addError('oh no'); }); }); - group("stream channel rules", () { - group("for the main stream:", () { + group('stream channel rules', () { + group('for the main stream:', () { test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); @@ -359,7 +359,7 @@ void main() { }, count: 1)); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(channel1.sink.close()); // Wait for the done event to be delivered. @@ -405,7 +405,7 @@ void main() { }); }); - group("for a virtual channel:", () { + group('for a virtual channel:', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -414,8 +414,8 @@ void main() { }); test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); @@ -426,7 +426,7 @@ void main() { }, count: 1)); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(virtual1.sink.close()); // Wait for the done event to be delivered. diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 070035e7ba..234f956efc 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -20,8 +20,8 @@ void main() { innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); - group("when a channel is set before accessing", () { - test("forwards events through the stream", () { + group('when a channel is set before accessing', () { + test('forwards events through the stream', () { completer.setChannel(innerChannel); expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); @@ -31,7 +31,7 @@ void main() { streamController.close(); }); - test("forwards events through the sink", () { + test('forwards events through the sink', () { completer.setChannel(innerChannel); expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); @@ -41,21 +41,21 @@ void main() { completer.channel.sink.close(); }); - test("forwards an error through the stream", () { - completer.setError("oh no"); - expect(completer.channel.stream.first, throwsA("oh no")); + test('forwards an error through the stream', () { + completer.setError('oh no'); + expect(completer.channel.stream.first, throwsA('oh no')); }); - test("drops sink events", () { - completer.setError("oh no"); + test('drops sink events', () { + completer.setError('oh no'); expect(completer.channel.sink.done, completes); completer.channel.sink.add(1); - completer.channel.sink.addError("oh no"); + completer.channel.sink.addError('oh no'); }); }); - group("when a channel is set after accessing", () { - test("forwards events through the stream", () async { + group('when a channel is set after accessing', () { + test('forwards events through the stream', () async { expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); await pumpEventQueue(); @@ -66,7 +66,7 @@ void main() { unawaited(streamController.close()); }); - test("forwards events through the sink", () async { + test('forwards events through the sink', () async { completer.channel.sink.add(1); completer.channel.sink.add(2); completer.channel.sink.add(3); @@ -77,25 +77,25 @@ void main() { expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards an error through the stream", () async { - expect(completer.channel.stream.first, throwsA("oh no")); + test('forwards an error through the stream', () async { + expect(completer.channel.stream.first, throwsA('oh no')); await pumpEventQueue(); - completer.setError("oh no"); + completer.setError('oh no'); }); - test("drops sink events", () async { + test('drops sink events', () async { expect(completer.channel.sink.done, completes); completer.channel.sink.add(1); - completer.channel.sink.addError("oh no"); + completer.channel.sink.addError('oh no'); await pumpEventQueue(); - completer.setError("oh no"); + completer.setError('oh no'); }); }); - group("forFuture", () { - test("forwards a StreamChannel", () { + group('forFuture', () { + test('forwards a StreamChannel', () { var channel = StreamChannelCompleter.fromFuture(Future.value(innerChannel)); channel.sink.add(1); @@ -107,9 +107,9 @@ void main() { expect(channel.stream.toList(), completion(equals([2]))); }); - test("forwards an error", () { - var channel = StreamChannelCompleter.fromFuture(Future.error("oh no")); - expect(channel.stream.toList(), throwsA("oh no")); + test('forwards an error', () { + var channel = StreamChannelCompleter.fromFuture(Future.error('oh no')); + expect(channel.stream.toList(), throwsA('oh no')); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 62f883fa5e..9b7a851d04 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -6,13 +6,13 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - group("asynchronously", () { + group('asynchronously', () { StreamChannelController controller; setUp(() { controller = StreamChannelController(); }); - test("forwards events from the local sink to the foreign stream", () { + test('forwards events from the local sink to the foreign stream', () { controller.local.sink ..add(1) ..add(2) @@ -21,7 +21,7 @@ void main() { expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards events from the foreign sink to the local stream", () { + test('forwards events from the foreign sink to the local stream', () { controller.foreign.sink ..add(1) ..add(2) @@ -31,27 +31,27 @@ void main() { }); test( - "with allowForeignErrors: false, shuts down the connection if an " - "error is added to the foreign channel", () { + 'with allowForeignErrors: false, shuts down the connection if an ' + 'error is added to the foreign channel', () { controller = StreamChannelController(allowForeignErrors: false); - controller.foreign.sink.addError("oh no"); - expect(controller.foreign.sink.done, throwsA("oh no")); + controller.foreign.sink.addError('oh no'); + expect(controller.foreign.sink.done, throwsA('oh no')); expect(controller.foreign.stream.toList(), completion(isEmpty)); expect(controller.local.sink.done, completes); expect(controller.local.stream.toList(), completion(isEmpty)); }); }); - group("synchronously", () { + group('synchronously', () { StreamChannelController controller; setUp(() { controller = StreamChannelController(sync: true); }); test( - "synchronously forwards events from the local sink to the foreign " - "stream", () { + 'synchronously forwards events from the local sink to the foreign ' + 'stream', () { var receivedEvent = false; var receivedError = false; var receivedDone = false; @@ -59,7 +59,7 @@ void main() { expect(event, equals(1)); receivedEvent = true; }), onError: expectAsync1((error) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); receivedError = true; }), onDone: expectAsync0(() { receivedDone = true; @@ -68,7 +68,7 @@ void main() { controller.local.sink.add(1); expect(receivedEvent, isTrue); - controller.local.sink.addError("oh no"); + controller.local.sink.addError('oh no'); expect(receivedError, isTrue); controller.local.sink.close(); @@ -76,8 +76,8 @@ void main() { }); test( - "synchronously forwards events from the foreign sink to the local " - "stream", () { + 'synchronously forwards events from the foreign sink to the local ' + 'stream', () { var receivedEvent = false; var receivedError = false; var receivedDone = false; @@ -85,7 +85,7 @@ void main() { expect(event, equals(1)); receivedEvent = true; }), onError: expectAsync1((error) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); receivedError = true; }), onDone: expectAsync0(() { receivedDone = true; @@ -94,7 +94,7 @@ void main() { controller.foreign.sink.add(1); expect(receivedEvent, isTrue); - controller.foreign.sink.addError("oh no"); + controller.foreign.sink.addError('oh no'); expect(receivedError, isTrue); controller.foreign.sink.close(); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 3f4e896b34..9bd5a86f85 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,16 +41,16 @@ void main() { expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); }); - test("transform() transforms the channel", () async { + test('transform() transforms the channel', () async { var transformed = channel .cast>() .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); unawaited(streamController.close()); - expect(await transformed.stream.toList(), equals(["foobar"])); + expect(await transformed.stream.toList(), equals(['foobar'])); - transformed.sink.add("fblthp"); + transformed.sink.add('fblthp'); unawaited(transformed.sink.close()); expect( sinkController.stream.toList(), @@ -59,39 +59,39 @@ void main() { ]))); }); - test("transformStream() transforms only the stream", () async { + test('transformStream() transforms only the stream', () async { var transformed = channel.cast().transformStream(const LineSplitter()); - streamController.add("hello world"); - streamController.add(" what\nis"); - streamController.add("\nup"); + streamController.add('hello world'); + streamController.add(' what\nis'); + streamController.add('\nup'); unawaited(streamController.close()); expect(await transformed.stream.toList(), - equals(["hello world what", "is", "up"])); + equals(['hello world what', 'is', 'up'])); - transformed.sink.add("fbl\nthp"); + transformed.sink.add('fbl\nthp'); unawaited(transformed.sink.close()); - expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); + expect(sinkController.stream.toList(), completion(equals(['fbl\nthp']))); }); - test("transformSink() transforms only the sink", () async { + test('transformSink() transforms only the sink', () async { var transformed = channel.cast().transformSink( StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); - streamController.add("fbl\nthp"); + streamController.add('fbl\nthp'); unawaited(streamController.close()); - expect(await transformed.stream.toList(), equals(["fbl\nthp"])); + expect(await transformed.stream.toList(), equals(['fbl\nthp'])); - transformed.sink.add("hello world"); - transformed.sink.add(" what\nis"); - transformed.sink.add("\nup"); + transformed.sink.add('hello world'); + transformed.sink.add(' what\nis'); + transformed.sink.add('\nup'); unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), - completion(equals(["hello world what", "is", "up"]))); + completion(equals(['hello world what', 'is', 'up']))); }); - test("changeStream() changes the stream", () { + test('changeStream() changes the stream', () { var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); @@ -107,7 +107,7 @@ void main() { expect(changed.stream.toList(), completion(equals([10]))); }); - test("changeSink() changes the sink", () { + test('changeSink() changes the sink', () { var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 803dc61f14..24aef03383 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -35,8 +35,8 @@ void main() { }); test( - "closing the event sink causes the stream to close before it emits any " - "more events", () async { + 'closing the event sink causes the stream to close before it emits any ' + 'more events', () async { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); @@ -53,8 +53,8 @@ void main() { }); test( - "closing the event sink before events are emitted causes the stream to " - "close immediately", () async { + 'closing the event sink before events are emitted causes the stream to ' + 'close immediately', () async { unawaited(channel.sink.close()); channel.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync2((_, __) {}, count: 0), diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index c9ff59f1e2..fa49689afe 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -19,14 +19,14 @@ void main() { streamController.stream, sinkController.sink); }); - group("with a broadcast stream", () { + group('with a broadcast stream', () { setUp(() { streamController = StreamController.broadcast(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); - test("buffers events", () async { + test('buffers events', () async { streamController.add(1); streamController.add(2); streamController.add(3); @@ -36,15 +36,15 @@ void main() { unawaited(streamController.close()); }); - test("only allows a single subscription", () { + test('only allows a single subscription', () { channel.stream.listen(null); expect(() => channel.stream.listen(null), throwsStateError); }); }); test( - "closing the event sink causes the stream to close before it emits any " - "more events", () { + 'closing the event sink causes the stream to close before it emits any ' + 'more events', () { streamController.add(1); streamController.add(2); streamController.add(3); @@ -58,7 +58,7 @@ void main() { completes); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(streamController.close()); // Wait for the done event to be delivered. @@ -105,12 +105,12 @@ void main() { await pumpEventQueue(); }); - test("forwards errors to the other endpoint", () { - channel.sink.addError("error"); - expect(sinkController.stream.first, throwsA("error")); + test('forwards errors to the other endpoint', () { + channel.sink.addError('error'); + expect(sinkController.stream.first, throwsA('error')); }); - test("Sink.done completes once the stream is done", () { + test('Sink.done completes once the stream is done', () { channel.stream.listen(null); expect(channel.sink.done, completes); streamController.close(); @@ -121,7 +121,7 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -131,7 +131,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -139,7 +139,7 @@ void main() { controller.close(); }); - group("with allowSinkErrors: false", () { + group('with allowSinkErrors: false', () { setUp(() { streamController = StreamController(); sinkController = StreamController(); @@ -148,15 +148,15 @@ void main() { allowSinkErrors: false); }); - test("forwards errors to Sink.done but not the stream", () { - channel.sink.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + test('forwards errors to Sink.done but not the stream', () { + channel.sink.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); sinkController.stream .listen(null, onError: expectAsync1((_) {}, count: 0)); }); - test("adding an error causes the stream to emit a done event", () { - expect(channel.sink.done, throwsA("oh no")); + test('adding an error causes the stream to emit a done event', () { + expect(channel.sink.done, throwsA('oh no')); streamController.add(1); streamController.add(2); @@ -165,21 +165,21 @@ void main() { expect( channel.stream .listen(expectAsync1((event) { - if (event == 2) channel.sink.addError("oh no"); + if (event == 2) channel.sink.addError('oh no'); }, count: 2)) .asFuture(), completes); }); - test("adding an error closes the inner sink", () { - channel.sink.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + test('adding an error closes the inner sink', () { + channel.sink.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); expect(sinkController.stream.toList(), completion(isEmpty)); }); test( - "adding an error via via addStream causes the stream to emit a done " - "event", () async { + 'adding an error via via addStream causes the stream to emit a done ' + 'event', () async { var canceled = false; var controller = StreamController(onCancel: () { canceled = true; @@ -188,8 +188,8 @@ void main() { // This future shouldn't get the error, because it's sent to [Sink.done]. expect(channel.sink.addStream(controller.stream), completes); - controller.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + controller.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); await pumpEventQueue(); expect(canceled, isTrue); From 364b71fa00dc3ee711b09d74f74b38c0ea93792a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 14 Jan 2020 13:35:10 -0800 Subject: [PATCH 077/138] Fix implicit casts (dart-lang/stream_channel#49) - Add some explicit casts. - Cast a `Stream` to `Stream` since we always expect to get a List out. --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/analysis_options.yaml | 2 ++ pkgs/stream_channel/lib/src/multi_channel.dart | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4f345106a3..8421292389 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.1.0 +## 2.1.0-dev * Require Dart `2.2.0` or later. diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index df4128a173..b36c8749b5 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,5 +1,7 @@ include: package:pedantic/analysis_options.yaml analyzer: + strong-mode: + implicit-casts: false # These are errors when building in Google errors: unused_import: error diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e0982ae19b..79f247e085 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -140,8 +140,8 @@ class _MultiChannel extends StreamChannelMixin (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _inner.stream.listen((message) { - var id = message[0]; + _innerStreamSubscription = _inner.stream.cast().listen((message) { + var id = message[0] as int; // If the channel was closed before an incoming message was processed, // ignore that message. @@ -156,7 +156,7 @@ class _MultiChannel extends StreamChannelMixin }); if (message.length > 1) { - controller.local.sink.add(message[1]); + controller.local.sink.add(message[1] as T); } else { // A message without data indicates that the channel has been closed. We // can just close the sink here without doing any more cleanup, because From 75f49eee3bd6ecd60d016ee106b38c7a8f9f1415 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 14 Jan 2020 15:11:08 -0800 Subject: [PATCH 078/138] Drop usages of Delegating*.typed (dart-lang/stream_channel#50) --- pkgs/stream_channel/lib/stream_channel.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index c806ec663b..56937929ab 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -176,5 +176,5 @@ abstract class StreamChannelMixin implements StreamChannel { @override StreamChannel cast() => StreamChannel( - DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); + stream.cast(), StreamController(sync: true)..stream.cast().pipe(sink)); } From 8358111d7856a31ac41d98831defd1379c4d43b3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 18 Mar 2020 13:13:45 -0700 Subject: [PATCH 079/138] Close send channel in test (dart-lang/stream_channel#54) Without closing this channel the VM will not exit. Refactor to `async/await` so that we can close the channel only after receiving the expected items. This allows running the test directly in the VM without the test runner. --- pkgs/stream_channel/test/isolate_channel_test.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index ab70f749b2..ec26fb647b 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -137,19 +137,21 @@ void main() { connectPort.close(); }); - test('create a connected pair of channels', () { + test('create a connected pair of channels', () async { var channel1 = IsolateChannel.connectReceive(connectPort); var channel2 = IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - expect(channel2.stream.take(3).toList(), completion(equals([1, 2, 3]))); + expect(await channel2.stream.take(3).toList(), equals([1, 2, 3])); channel2.sink.add(4); channel2.sink.add(5); channel2.sink.add(6); - expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); + expect(await channel1.stream.take(3).toList(), equals([4, 5, 6])); + + await channel2.sink.close(); }); test('the receiving channel produces an error if it gets the wrong message', From eb109aef39742e86328a6d50b763b853484600a4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 2 Apr 2020 10:25:21 -0700 Subject: [PATCH 080/138] Rewrite doc comment to refer to TypeError (dart-lang/stream_channel#57) This will be the type going forward. Keep a reference to `CastError` for now, we can drop it after a few SDK releases. --- pkgs/stream_channel/lib/stream_channel.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 56937929ab..4722aa39c6 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -126,8 +126,9 @@ abstract class StreamChannel { /// Returns a copy of this with the generic type coerced to [S]. /// /// If any events emitted by [stream] aren't of type [S], they're converted - /// into [CastError] events. Similarly, if any events are added to [sink] that - /// aren't of type [S], a [CastError] is thrown. + /// into [TypeError] events (`CastError` on some SDK versions). Similarly, if + /// any events are added to [sink] that aren't of type [S], a [TypeError] is + /// thrown. StreamChannel cast(); } From 1f61afe1f1885427a14a4fc40225382c1844e6a5 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 15 Jul 2020 18:58:38 -0700 Subject: [PATCH 081/138] Merge the null_safety branch into master (dart-lang/stream_channel#60) --- pkgs/stream_channel/.travis.yml | 17 +--- pkgs/stream_channel/CHANGELOG.md | 4 +- pkgs/stream_channel/analysis_options.yaml | 2 + .../lib/src/close_guarantee_channel.dart | 17 ++-- pkgs/stream_channel/lib/src/disconnector.dart | 12 +-- .../lib/src/guarantee_channel.dart | 23 +++--- .../lib/src/isolate_channel.dart | 2 +- .../lib/src/json_document_transformer.dart | 6 +- .../stream_channel/lib/src/multi_channel.dart | 28 +++---- .../lib/src/stream_channel_completer.dart | 4 +- .../lib/src/stream_channel_controller.dart | 4 +- pkgs/stream_channel/pubspec.yaml | 81 ++++++++++++++++++- .../test/disconnector_test.dart | 8 +- .../test/isolate_channel_test.dart | 8 +- .../test/json_document_transformer_test.dart | 6 +- .../test/multi_channel_test.dart | 22 ++--- .../test/stream_channel_completer_test.dart | 8 +- .../test/stream_channel_controller_test.dart | 4 +- .../test/stream_channel_test.dart | 6 +- .../test/with_close_guarantee_test.dart | 4 +- .../test/with_guarantees_test.dart | 8 +- 21 files changed, 171 insertions(+), 103 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index d6a5454960..b4907d5d15 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,27 +1,16 @@ language: dart dart: -- 2.2.0 - dev dart_task: - test: --platform vm,chrome - -matrix: - include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.2.0 - dart_task: - dartanalyzer: --fatal-warnings . +- dartfmt +- dartanalyzer: --fatal-infos --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8421292389..2c4a13ce62 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,6 @@ -## 2.1.0-dev +## 2.1.0-nullsafety -* Require Dart `2.2.0` or later. +* Migrate to null safety. ## 2.0.0 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index b36c8749b5..8a712df8f4 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,6 +8,8 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error + enable-experiment: + - non-nullable linter: rules: diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 60916d002e..25f5022352 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -16,14 +16,14 @@ import '../stream_channel.dart'; class CloseGuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _stream; - _CloseGuaranteeStream _stream; + late final _CloseGuaranteeStream _stream; @override StreamSink get sink => _sink; - _CloseGuaranteeSink _sink; + late final _CloseGuaranteeSink _sink; /// The subscription to the inner stream. - StreamSubscription _subscription; + StreamSubscription? _subscription; /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; @@ -48,8 +48,8 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); @override - StreamSubscription listen(void Function(T) onData, - {Function onError, void Function() onDone, bool cancelOnError}) { + StreamSubscription listen(void Function(T)? onData, + {Function? onError, void Function()? onDone, bool? cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything // but a done event. if (_channel._disconnected) { @@ -80,10 +80,11 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { Future close() { var done = super.close(); _channel._disconnected = true; - if (_channel._subscription != null) { + var subscription = _channel._subscription; + if (subscription != null) { // Don't dispatch anything but a done event. - _channel._subscription.onData(null); - _channel._subscription.onError(null); + subscription.onData(null); + subscription.onError(null); } return done; } diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index e8835374f3..a424146b86 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -74,11 +74,11 @@ class _DisconnectorSink implements StreamSink { /// The subscription to the stream passed to [addStream], if a stream is /// currently being added. - StreamSubscription _addStreamSubscription; + StreamSubscription? _addStreamSubscription; /// The completer for the future returned by [addStream], if a stream is /// currently being added. - Completer _addStreamCompleter; + Completer? _addStreamCompleter; /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; @@ -97,7 +97,7 @@ class _DisconnectorSink implements StreamSink { } @override - void addError(error, [StackTrace stackTrace]) { + void addError(error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); @@ -117,8 +117,8 @@ class _DisconnectorSink implements StreamSink { _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, - onError: _inner.addError, onDone: _addStreamCompleter.complete); - return _addStreamCompleter.future.then((_) { + onError: _inner.addError, onDone: _addStreamCompleter!.complete); + return _addStreamCompleter!.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; }); @@ -143,7 +143,7 @@ class _DisconnectorSink implements StreamSink { var future = _inner.close(); if (_inAddStream) { - _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter!.complete(_addStreamSubscription!.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; } diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index cfee99ee5a..4780b046fa 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -17,17 +17,17 @@ class GuaranteeChannel extends StreamChannelMixin { @override StreamSink get sink => _sink; - _GuaranteeSink _sink; + late final _GuaranteeSink _sink; /// The controller for [stream]. /// /// This intermediate controller allows us to continue listening for a done /// event even after the user has canceled their subscription, and to send our /// own done event when the sink is closed. - StreamController _streamController; + late final StreamController _streamController; /// The subscription to the inner stream. - StreamSubscription _subscription; + StreamSubscription? _subscription; /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; @@ -64,7 +64,8 @@ class GuaranteeChannel extends StreamChannelMixin { /// should stop emitting events. void _onSinkDisconnected() { _disconnected = true; - if (_subscription != null) _subscription.cancel(); + var subscription = _subscription; + if (subscription != null) subscription.cancel(); _streamController.close(); } } @@ -95,11 +96,11 @@ class _GuaranteeSink implements StreamSink { /// The subscription to the stream passed to [addStream], if a stream is /// currently being added. - StreamSubscription _addStreamSubscription; + StreamSubscription? _addStreamSubscription; /// The completer for the future returned by [addStream], if a stream is /// currently being added. - Completer _addStreamCompleter; + Completer? _addStreamCompleter; /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; @@ -125,7 +126,7 @@ class _GuaranteeSink implements StreamSink { } @override - void addError(error, [StackTrace stackTrace]) { + void addError(error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); @@ -139,7 +140,7 @@ class _GuaranteeSink implements StreamSink { /// /// This is called from [addStream], so it shouldn't fail if a stream is being /// added. - void _addError(error, [StackTrace stackTrace]) { + void _addError(Object error, [StackTrace? stackTrace]) { if (_allowErrors) { _inner.addError(error, stackTrace); return; @@ -166,8 +167,8 @@ class _GuaranteeSink implements StreamSink { _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, - onError: _addError, onDone: _addStreamCompleter.complete); - return _addStreamCompleter.future.then((_) { + onError: _addError, onDone: _addStreamCompleter!.complete); + return _addStreamCompleter!.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; }); @@ -199,7 +200,7 @@ class _GuaranteeSink implements StreamSink { if (!_doneCompleter.isCompleted) _doneCompleter.complete(); if (!_inAddStream) return; - _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter!.complete(_addStreamSubscription!.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; } diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 8c1b568420..55c98143f0 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -51,7 +51,7 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - StreamSubscription subscription; + late StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 8bffc8ab93..237193b867 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -18,14 +18,14 @@ import 'stream_channel_transformer.dart'; /// If the transformed channel emits invalid JSON, this emits a /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. -final StreamChannelTransformer jsonDocument = +final StreamChannelTransformer jsonDocument = const _JsonDocument(); -class _JsonDocument implements StreamChannelTransformer { +class _JsonDocument implements StreamChannelTransformer { const _JsonDocument(); @override - StreamChannel bind(StreamChannel channel) { + StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(jsonDecode); var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 79f247e085..e1e25ea049 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -73,7 +73,7 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([int id]); + VirtualChannel virtualChannel([int? id]); } /// The implementation of [MultiChannel]. @@ -85,10 +85,10 @@ class _MultiChannel extends StreamChannelMixin /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - StreamChannel _inner; + StreamChannel? _inner; /// The subscription to [_inner].stream. - StreamSubscription _innerStreamSubscription; + StreamSubscription? _innerStreamSubscription; @override Stream get stream => _mainController.foreign.stream; @@ -132,15 +132,15 @@ class _MultiChannel extends StreamChannelMixin /// it's coming from a channel that was originally created locally. var _nextId = 1; - _MultiChannel(this._inner) { + _MultiChannel(StreamChannel inner) : _inner = inner { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. _controllers[0] = _mainController; _mainController.local.stream.listen( - (message) => _inner.sink.add([0, message]), + (message) => _inner!.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _inner.stream.cast().listen((message) { + _innerStreamSubscription = _inner!.stream.cast().listen((message) { var id = message[0] as int; // If the channel was closed before an incoming message was processed, @@ -170,7 +170,7 @@ class _MultiChannel extends StreamChannelMixin } @override - VirtualChannel virtualChannel([int id]) { + VirtualChannel virtualChannel([int? id]) { int inputId; int outputId; if (id != null) { @@ -194,11 +194,11 @@ class _MultiChannel extends StreamChannelMixin return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); } - StreamChannelController controller; + late StreamChannelController controller; if (_pendingIds.remove(inputId)) { // If we've already received messages for this channel, use the controller // where those messages are buffered. - controller = _controllers[inputId]; + controller = _controllers[inputId]!; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { throw ArgumentError('A virtual channel with id $id already exists.'); @@ -208,7 +208,7 @@ class _MultiChannel extends StreamChannelMixin } controller.local.stream.listen( - (message) => _inner.sink.add([outputId, message]), + (message) => _inner!.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); @@ -218,21 +218,21 @@ class _MultiChannel extends StreamChannelMixin /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { _closedIds.add(inputId); - var controller = _controllers.remove(inputId); + var controller = _controllers.remove(inputId)!; controller.local.sink.close(); if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. - _inner.sink.add([outputId]); + _inner!.sink.add([outputId]); if (_controllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. void _closeInnerChannel() { - _inner.sink.close(); - _innerStreamSubscription.cancel(); + _inner!.sink.close(); + _innerStreamSubscription!.cancel(); _inner = null; // Convert this to a list because the close is dispatched synchronously, and diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index a14ffde44a..f6fef25dc1 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -22,7 +22,7 @@ class StreamChannelCompleter { /// The channel for this completer. StreamChannel get channel => _channel; - StreamChannel _channel; + late final StreamChannel _channel; /// Whether [setChannel] has been called. bool _set = false; @@ -66,7 +66,7 @@ class StreamChannelCompleter { /// /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. - void setError(error, [StackTrace stackTrace]) { + void setError(Object error, [StackTrace? stackTrace]) { if (_set) throw StateError('The channel has already been set.'); _set = true; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 136886df70..5c788667d3 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -33,14 +33,14 @@ class StreamChannelController { /// This channel should be used directly by the creator of this /// [StreamChannelController] to send and receive events. StreamChannel get local => _local; - StreamChannel _local; + late final StreamChannel _local; /// The foreign channel. /// /// This channel should be returned to external users so they can communicate /// with [local]. StreamChannel get foreign => _foreign; - StreamChannel _foreign; + late final StreamChannel _foreign; /// Creates a [StreamChannelController]. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 61e78c0f3d..e4208b9539 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-dev +version: 2.1.0-nullsafety description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,11 +8,86 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dependencies: - async: '>=1.11.0 <3.0.0' + async: '>=2.5.0-nullsafety <2.5.0' dev_dependencies: pedantic: ^1.8.0 test: ^1.2.0 + +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + collection: 1.15.0-nullsafety + js: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/js + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: 1.3.0-nullsafety + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + pool: + git: + url: git://github.com/dart-lang/pool.git + ref: null_safety + source_maps: + git: + url: git://github.com/dart-lang/source_maps.git + ref: null_safety + source_map_stack_trace: + git: + url: git://github.com/dart-lang/source_map_stack_trace.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stack_trace: + git: + url: git://github.com/dart-lang/stack_trace.git + ref: null_safety + string_scanner: + git: + url: git://github.com/dart-lang/string_scanner.git + ref: null_safety + term_glyph: + git: + url: git://github.com/dart-lang/term_glyph.git + ref: null_safety + test: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test_core + ref: null_safety diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index ec0c64bc06..4f16012bf9 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -10,10 +10,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - Disconnector disconnector; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late Disconnector disconnector; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index ec26fb647b..a1ec37eafd 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -13,9 +13,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - ReceivePort receivePort; - SendPort sendPort; - StreamChannel channel; + late ReceivePort receivePort; + late SendPort sendPort; + late StreamChannel channel; setUp(() { receivePort = ReceivePort(); var receivePortForSend = ReceivePort(); @@ -128,7 +128,7 @@ void main() { }); group('connect constructors', () { - ReceivePort connectPort; + late ReceivePort connectPort; setUp(() { connectPort = ReceivePort(); }); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 3ccce4ead5..48d8f72917 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -9,9 +9,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0fa1df9ea9..00bcabe3bc 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -7,9 +7,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamChannelController controller; - MultiChannel channel1; - MultiChannel channel2; + late StreamChannelController controller; + late MultiChannel channel1; + late MultiChannel channel2; setUp(() { controller = StreamChannelController(); channel1 = MultiChannel(controller.local); @@ -85,8 +85,8 @@ void main() { }); group('a locally-created virtual channel', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -185,8 +185,8 @@ void main() { }); group('a remotely-created virtual channel', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -297,8 +297,8 @@ void main() { }); group('when the underlying stream', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -406,8 +406,8 @@ void main() { }); group('for a virtual channel:', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 234f956efc..a874925009 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -9,10 +9,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamChannelCompleter completer; - StreamController streamController; - StreamController sinkController; - StreamChannel innerChannel; + late StreamChannelCompleter completer; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel innerChannel; setUp(() { completer = StreamChannelCompleter(); streamController = StreamController(); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 9b7a851d04..3d661e3020 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -7,7 +7,7 @@ import 'package:test/test.dart'; void main() { group('asynchronously', () { - StreamChannelController controller; + late StreamChannelController controller; setUp(() { controller = StreamChannelController(); }); @@ -44,7 +44,7 @@ void main() { }); group('synchronously', () { - StreamChannelController controller; + late StreamChannelController controller; setUp(() { controller = StreamChannelController(sync: true); }); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 9bd5a86f85..e101d206d4 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -11,9 +11,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 24aef03383..decc2b4489 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -17,8 +17,8 @@ final _delaySinkTransformer = StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { - StreamChannelController controller; - StreamChannel channel; + late StreamChannelController controller; + late StreamChannel channel; setUp(() { controller = StreamChannelController(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index fa49689afe..a19dc58c2b 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -9,9 +9,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); @@ -152,7 +152,7 @@ void main() { channel.sink.addError('oh no'); expect(channel.sink.done, throwsA('oh no')); sinkController.stream - .listen(null, onError: expectAsync1((_) {}, count: 0)); + .listen(null, onError: expectAsync1((dynamic _) {}, count: 0)); }); test('adding an error causes the stream to emit a done event', () { From e61fb5e430f83db5101a749239d2b4eb214ab8b9 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:41 -0700 Subject: [PATCH 082/138] update for the 2.10 dev sdk (dart-lang/stream_channel#61) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/stream_channel/.travis.yml | 4 +- pkgs/stream_channel/pubspec.yaml | 76 ++++++++++++-------------------- 2 files changed, 30 insertions(+), 50 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index b4907d5d15..1768146748 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- dev +- preview/raw/2.10.0-0.2-dev dart_task: - test: --platform vm,chrome @@ -10,7 +10,7 @@ dart_task: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index e4208b9539..0dc7c9939c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -8,7 +8,8 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' @@ -19,75 +20,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: - git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety - collection: 1.15.0-nullsafety + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git js: git: url: git://github.com/dart-lang/sdk.git path: pkg/js + ref: 2-10-pkgs matcher: + git: git://github.com/dart-lang/matcher.git + meta: git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety - meta: 1.3.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git pool: - git: - url: git://github.com/dart-lang/pool.git - ref: null_safety + git: git://github.com/dart-lang/pool.git source_maps: - git: - url: git://github.com/dart-lang/source_maps.git - ref: null_safety + git: git://github.com/dart-lang/source_maps.git source_map_stack_trace: - git: - url: git://github.com/dart-lang/source_map_stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stack_trace: - git: - url: git://github.com/dart-lang/stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/stack_trace.git string_scanner: - git: - url: git://github.com/dart-lang/string_scanner.git - ref: null_safety + git: git://github.com/dart-lang/string_scanner.git term_glyph: - git: - url: git://github.com/dart-lang/term_glyph.git - ref: null_safety - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - ref: null_safety + git: git://github.com/dart-lang/term_glyph.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git path: pkgs/test_core - ref: null_safety + test: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From 83c6c48430414ec2fa110e71eeed0bc7d0d20d49 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 13:47:48 -0700 Subject: [PATCH 083/138] Delete .test_config No longer used --- pkgs/stream_channel/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stream_channel/.test_config diff --git a/pkgs/stream_channel/.test_config b/pkgs/stream_channel/.test_config deleted file mode 100644 index 352d2feeec..0000000000 --- a/pkgs/stream_channel/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} From 729a4c6f74a4b5efcd42a5cdd12182c678486db6 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 14:13:08 -0700 Subject: [PATCH 084/138] Update Travis-CI to use dev channel (dart-lang/stream_channel#62) --- pkgs/stream_channel/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 1768146748..be2f29d029 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- preview/raw/2.10.0-0.2-dev +- dev dart_task: - test: --platform vm,chrome From dfc6fd73f92f7fdd4ae327b1f31860c89db16baf Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 30 Jul 2020 10:00:20 -0700 Subject: [PATCH 085/138] Remove the author section from pubspec (dart-lang/stream_channel#63) Resolves a warning from the pub tool that this field is no longer used. --- pkgs/stream_channel/CHANGELOG.md | 2 ++ pkgs/stream_channel/pubspec.yaml | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2c4a13ce62..98c1e6c298 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.1.0-nullsafety.1-dev + ## 2.1.0-nullsafety * Migrate to null safety. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0dc7c9939c..5895aee593 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,9 @@ name: stream_channel -version: 2.1.0-nullsafety +version: 2.1.0-nullsafety.1-dev description: >- An abstraction for two-way communication channels based on the Dart Stream class. -author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: From bb724781b640a759fbd7384b978310d1c66e00d2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:17:03 -0700 Subject: [PATCH 086/138] Prepare for the 2.11 dev SDKs (dart-lang/stream_channel#64) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/stream_channel/CHANGELOG.md | 4 +++- pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 98c1e6c298..83da2abecd 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,6 @@ -## 2.1.0-nullsafety.1-dev +## 2.1.0-nullsafety.1 + +* Allow 2.10 stable and 2.11.0 dev SDK versions. ## 2.1.0-nullsafety diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5895aee593..b8f0f97f84 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.1-dev +version: 2.1.0-nullsafety.1 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,7 +8,7 @@ homepage: https://github.com/dart-lang/stream_channel environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' From 18d7aa816c879f767b5b134a3f92d01413e3b772 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 20 Oct 2020 16:12:08 -0700 Subject: [PATCH 087/138] Remove unused dart:async import The only members of dart:async used here (Future and/or Stream) are exported from dart:core now. --- pkgs/stream_channel/lib/src/stream_channel_completer.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index f6fef25dc1..5a824c1f36 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -2,8 +2,6 @@ // 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:async/async.dart'; import '../stream_channel.dart'; From 85fcb605844bd414e433993484864c55cabfdb90 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:10:17 -0700 Subject: [PATCH 088/138] allow the 2.12 prerelease sdks (dart-lang/stream_channel#66) --- pkgs/stream_channel/CHANGELOG.md | 4 +++ pkgs/stream_channel/pubspec.yaml | 62 +++----------------------------- 2 files changed, 8 insertions(+), 58 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 83da2abecd..95f370c38d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0-nullsafety.2 + +* Allow prerelease versions of the 2.12 sdk. + ## 2.1.0-nullsafety.1 * Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index b8f0f97f84..9259c34c4b 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.1 +version: 2.1.0-nullsafety.2 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,65 +8,11 @@ homepage: https://github.com/dart-lang/stream_channel environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.10.0-0 <2.12.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' dev_dependencies: - pedantic: ^1.8.0 - test: ^1.2.0 - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety From e8efb13bda913507914d61e0c689ca38465c0d2f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 14:33:09 -0800 Subject: [PATCH 089/138] Bump SDK constraints for pub (dart-lang/stream_channel#67) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/stream_channel/CHANGELOG.md | 5 +++++ pkgs/stream_channel/pubspec.yaml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 95f370c38d..ea31ffe2c0 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.0-nullsafety.3 + +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. + ## 2.1.0-nullsafety.2 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9259c34c4b..d11a3567f1 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.2 +version: 2.1.0-nullsafety.3 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -7,8 +7,7 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dependencies: async: '>=2.5.0-nullsafety <2.5.0' From 87fb3b0c3eb1c2c6f03dda3d73b659d05a6422a1 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 11 Nov 2020 09:33:06 -0800 Subject: [PATCH 090/138] remove redundant experiment --- pkgs/stream_channel/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8a712df8f4..b36c8749b5 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,8 +8,6 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error - enable-experiment: - - non-nullable linter: rules: From f2dcd319ec1efca9d01abd5500436e2cb63e4c53 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 29 Dec 2020 22:31:22 -0800 Subject: [PATCH 091/138] Remove unnecessary import --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 237193b867..3feda43fdf 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,7 +7,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. From 85a211c9fc11741d70310c39c7142cde5d18db5e Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 16:38:42 +0100 Subject: [PATCH 092/138] Migrate to GitHub Actions (dart-lang/stream_channel#70) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 64 +++++++++++++++++++ pkgs/stream_channel/.travis.yml | 17 ----- 2 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 pkgs/stream_channel/.github/workflows/test-package.yml delete mode 100644 pkgs/stream_channel/.travis.yml diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml new file mode 100644 index 0000000000..0a2a874338 --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml deleted file mode 100644 index be2f29d029..0000000000 --- a/pkgs/stream_channel/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: dart - -dart: -- dev - -dart_task: -- test: --platform vm,chrome -- dartfmt -- dartanalyzer: --fatal-infos --fatal-warnings . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 8fff9b57e1dc76c9503d15f322da041f651e68a0 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 2 Feb 2021 11:20:18 -0800 Subject: [PATCH 093/138] Revert "Remove unnecessary import" (dart-lang/stream_channel#71) This reverts commit f2dcd319ec1efca9d01abd5500436e2cb63e4c53. Since this has not been published or rolled through to the SDK or Flutter we will hold it back to reduce risk. --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 3feda43fdf..237193b867 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; +import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. From f114ba87d21f5259bd413edb4dffa4f8728cae7b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 13:31:22 -0800 Subject: [PATCH 094/138] Prepare to publish for stable null safety (dart-lang/stream_channel#72) --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ea31ffe2c0..2bb6c1f269 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Stable release for null safety. + ## 2.1.0-nullsafety.3 * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index d11a3567f1..e7f6c7a7c8 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.3 +version: 2.1.0 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -10,7 +10,7 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - async: '>=2.5.0-nullsafety <2.5.0' + async: ^2.5.0 dev_dependencies: pedantic: ^1.10.0-nullsafety From 2cb754777407c53b3a608f0c87df6645d7f77592 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:12:05 -0700 Subject: [PATCH 095/138] Update LICENSE Changes to comply to internal review --- pkgs/stream_channel/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/LICENSE b/pkgs/stream_channel/LICENSE index de31e1a0a4..dbd2843a08 100644 --- a/pkgs/stream_channel/LICENSE +++ b/pkgs/stream_channel/LICENSE @@ -1,4 +1,5 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 242cca39e056cbb009a7f28bdca1d8457f811b4a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 May 2021 10:44:22 -0700 Subject: [PATCH 096/138] Remove unneeded imports (dart-lang/stream_channel#74) All cleanup null-safety bits from pubspec --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - pkgs/stream_channel/pubspec.yaml | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 237193b867..3feda43fdf 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,7 +7,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index e7f6c7a7c8..d4a7173616 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,11 +7,11 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + pedantic: ^1.10.0 + test: ^1.16.0 From da7d979f2c3dc1d7262c5d10d0e3960bc0fbd6c5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 5 Jun 2021 12:55:29 -0700 Subject: [PATCH 097/138] add dependabot --- pkgs/stream_channel/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/stream_channel/.github/dependabot.yml diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml new file mode 100644 index 0000000000..430a85e7d0 --- /dev/null +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 2c5c7e9b563e3013b30d63fc6ff257f551dd8b97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:41:09 -0700 Subject: [PATCH 098/138] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/stream_channel#75) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kevin Moore --- pkgs/stream_channel/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 0a2a874338..bd93fbed85 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From 1996879bda283a1a6672277525046ba54342ec0a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 11 Nov 2021 14:14:13 -0800 Subject: [PATCH 099/138] Migrate to pkg:lints recommended (dart-lang/stream_channel#76) * Migrate to pkg:lints recommended * require dart 2.13, drop prerelease changelog entries --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 21 ++++--------------- pkgs/stream_channel/analysis_options.yaml | 10 +++++---- pkgs/stream_channel/pubspec.yaml | 6 +++--- .../test/disconnector_test.dart | 1 - .../test/isolate_channel_test.dart | 2 -- .../test/multi_channel_test.dart | 3 ++- .../test/stream_channel_completer_test.dart | 1 - .../test/stream_channel_test.dart | 1 - .../test/with_close_guarantee_test.dart | 1 - .../test/with_guarantees_test.dart | 1 - 11 files changed, 16 insertions(+), 33 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index bd93fbed85..17c7d20d2b 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2bb6c1f269..89736d95f6 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,23 +1,10 @@ -## 2.1.0 - -* Stable release for null safety. - -## 2.1.0-nullsafety.3 - -* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release - guidelines. +## 2.1.1-dev -## 2.1.0-nullsafety.2 +* Require Dart 2.14 -* Allow prerelease versions of the 2.12 sdk. - -## 2.1.0-nullsafety.1 - -* Allow 2.10 stable and 2.11.0 dev SDK versions. - -## 2.1.0-nullsafety +## 2.1.0 -* Migrate to null safety. +* Stable release for null safety. ## 2.0.0 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index b36c8749b5..8465834c44 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,4 +1,5 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false @@ -11,7 +12,8 @@ analyzer: linter: rules: - - annotate_overrides - comment_references - - prefer_generic_function_type_aliases - - prefer_typing_uninitialized_variables + - always_declare_return_types + - omit_local_variable_types + - prefer_single_quotes + - unawaited_futures diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index d4a7173616..17948bcfad 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0 +version: 2.1.1-dev description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -7,11 +7,11 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - pedantic: ^1.10.0 + lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 4f16012bf9..66773b59cd 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index a1ec37eafd..a754421a9b 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -3,11 +3,9 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') - import 'dart:async'; import 'dart:isolate'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 00bcabe3bc..763e6b8290 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -2,7 +2,8 @@ // 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 'package:pedantic/pedantic.dart'; +import 'dart:async'; + import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index a874925009..22db01a760 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index e101d206d4..76edbdf91f 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index decc2b4489..a18f09fe19 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index a19dc58c2b..849e304919 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; From 8ebfdaecdabae533af70a6f19391cd08b3faac57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:15:55 -0800 Subject: [PATCH 100/138] Bump actions/checkout from 2 to 3 (dart-lang/stream_channel#78) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 17c7d20d2b..9de6d54aa6 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From 3ec468e3536cb3f000aa6c9ec57d2c919740b3c0 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 20:08:41 +0000 Subject: [PATCH 101/138] populate the pubspec repository field --- pkgs/stream_channel/CHANGELOG.md | 2 ++ pkgs/stream_channel/README.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 3 +-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 89736d95f6..0f8da15487 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,8 @@ ## 2.1.1-dev * Require Dart 2.14 +* Migrate to `package:lints`. +* Populate the pubspec `repository` field. ## 2.1.0 diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index 2ec970b8ef..ae1ea219d4 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) +[![package publisher](https://img.shields.io/pub/publisher/stream_channel.svg)](https://pub.dev/packages/stream_channel/publisher) + This package exposes the `StreamChannel` interface, which represents a two-way communication channel. Each `StreamChannel` exposes a `Stream` for receiving data and a `StreamSink` for sending it. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 17948bcfad..5e86fc3ebe 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,9 @@ name: stream_channel version: 2.1.1-dev - description: >- An abstraction for two-way communication channels based on the Dart Stream class. -homepage: https://github.com/dart-lang/stream_channel +repository: https://github.com/dart-lang/stream_channel environment: sdk: '>=2.14.0 <3.0.0' From 1183418e47c1d28dfa3c5db6f466910cd7c1c87a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 20 Sep 2022 12:16:54 -0700 Subject: [PATCH 102/138] Handle non-int multichannel message IDs (dart-lang/stream_channel#80) When running in wasm, a number in a `List` will be parsed as a `double`. On the web the `as int` cast succeeds, but in dart2wasm it fails. Cast to `num` and use `toInt()` to more reliably get an `int` value. --- pkgs/stream_channel/CHANGELOG.md | 3 +++ pkgs/stream_channel/lib/src/multi_channel.dart | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0f8da15487..badeaf737d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -3,6 +3,9 @@ * Require Dart 2.14 * Migrate to `package:lints`. * Populate the pubspec `repository` field. +* Handle multichannel messages where the ID element is a `double` at runtime + instead of an `int`. When reading an array with `dart2wasm` numbers within the + array are parsed as `double`. ## 2.1.0 diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e1e25ea049..a78ddbcf47 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -141,7 +141,7 @@ class _MultiChannel extends StreamChannelMixin onDone: () => _closeChannel(0, 0)); _innerStreamSubscription = _inner!.stream.cast().listen((message) { - var id = message[0] as int; + var id = (message[0] as num).toInt(); // If the channel was closed before an incoming message was processed, // ignore that message. From 5ad2e2ddf016f54053ea5b7cf880e4d2ac8a4181 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 21 Sep 2022 12:31:46 -0700 Subject: [PATCH 103/138] Prepare to publish (dart-lang/stream_channel#81) Drop changelog entry for non-user-facing change. Drop `-dev` suffix from version. --- pkgs/stream_channel/CHANGELOG.md | 3 +-- pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index badeaf737d..2b90a0a767 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,6 @@ -## 2.1.1-dev +## 2.1.1 * Require Dart 2.14 -* Migrate to `package:lints`. * Populate the pubspec `repository` field. * Handle multichannel messages where the ID element is a `double` at runtime instead of an `int`. When reading an array with `dart2wasm` numbers within the diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5e86fc3ebe..ff6a50c681 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.1-dev +version: 2.1.1 description: >- An abstraction for two-way communication channels based on the Dart Stream class. From 34bf35867217b0df4afde8e5e47b1b9547777dbd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 10 Nov 2022 03:30:31 -0800 Subject: [PATCH 104/138] blast_repo fixes (dart-lang/stream_channel#82) Dependabot GitHub Action --- pkgs/stream_channel/.github/dependabot.yml | 16 +++++++--------- .../.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 430a85e7d0..1603cdd9ee 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -1,11 +1,9 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates version: 2 -updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9de6d54aa6..4e2ee9d505 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From d31e1c8b97298fd02144157d2d771165b264a89d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:04:28 -0800 Subject: [PATCH 105/138] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/stream_channel#83) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 4e2ee9d505..9c93ba9988 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 1e06bc994c9e3d98779e6d25b212da9aa7d65986 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 21:31:41 -0800 Subject: [PATCH 106/138] Migrate from no-implicit-casts to strict-casts (dart-lang/stream_channel#84) --- pkgs/stream_channel/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8465834c44..517b5976fa 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true # These are errors when building in Google errors: unused_import: error From 4a851418acb026f4c1ccde05a04e58017429ceac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 21:54:55 -0800 Subject: [PATCH 107/138] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/stream_channel#86) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9c93ba9988..bdfd06d552 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From b4ae743353e14fcc238ee94042dd497f5d61b185 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:37:09 -0800 Subject: [PATCH 108/138] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/stream_channel#85) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index bdfd06d552..8c8f4ab69c 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.14.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 865feb6c88be01d025234f8e0b43699d8fdf2e75 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Feb 2023 10:01:30 -0800 Subject: [PATCH 109/138] move to pkg:dart_flutter_team_lints lints, fix code, bump min SDK (dart-lang/stream_channel#87) --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/analysis_options.yaml | 9 ++------- .../lib/src/close_guarantee_channel.dart | 4 ++-- pkgs/stream_channel/lib/src/disconnector.dart | 2 +- pkgs/stream_channel/lib/src/guarantee_channel.dart | 4 ++-- pkgs/stream_channel/lib/src/multi_channel.dart | 4 ++-- pkgs/stream_channel/lib/stream_channel.dart | 6 +++--- pkgs/stream_channel/pubspec.yaml | 6 +++--- pkgs/stream_channel/test/disconnector_test.dart | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 2 ++ pkgs/stream_channel/test/multi_channel_test.dart | 14 ++++++++------ 12 files changed, 31 insertions(+), 28 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 8c8f4ab69c..20b28decec 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.14.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2b90a0a767..0d73828395 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.2-dev + +* Require Dart 2.19 + ## 2.1.1 * Require Dart 2.14 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 517b5976fa..8e5d4a792b 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,14 +1,8 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true - # These are errors when building in Google - errors: - unused_import: error - unused_element: error - unused_local_variable: error - dead_code: error linter: rules: @@ -17,3 +11,4 @@ linter: - omit_local_variable_types - prefer_single_quotes - unawaited_futures + - use_super_parameters diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 25f5022352..13432d17df 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -12,7 +12,7 @@ import '../stream_channel.dart'; /// that closing the sink causes the stream to close before it emits any more /// events /// -/// This is exposed via [new StreamChannel.withCloseGuarantee]. +/// This is exposed via [StreamChannel.withCloseGuarantee]. class CloseGuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _stream; @@ -74,7 +74,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { /// The [CloseGuaranteeChannel] this belongs to. final CloseGuaranteeChannel _channel; - _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + _CloseGuaranteeSink(super.inner, this._channel); @override Future close() { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index a424146b86..61969cbf8f 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -97,7 +97,7 @@ class _DisconnectorSink implements StreamSink { } @override - void addError(error, [StackTrace? stackTrace]) { + void addError(Object error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 4780b046fa..2aa8b7b972 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -10,7 +10,7 @@ import '../stream_channel.dart'; /// A [StreamChannel] that enforces the stream channel guarantees. /// -/// This is exposed via [new StreamChannel.withGuarantees]. +/// This is exposed via [StreamChannel.withGuarantees]. class GuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _streamController.stream; @@ -126,7 +126,7 @@ class _GuaranteeSink implements StreamSink { } @override - void addError(error, [StackTrace? stackTrace]) { + void addError(Object error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a78ddbcf47..82f59c7c94 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -237,7 +237,7 @@ class _MultiChannel extends StreamChannelMixin // Convert this to a list because the close is dispatched synchronously, and // that could conceivably remove a controller from [_controllers]. - for (var controller in List.from(_controllers.values)) { + for (var controller in _controllers.values.toList(growable: false)) { controller.local.sink.close(); } _controllers.clear(); @@ -269,5 +269,5 @@ class VirtualChannel extends StreamChannelMixin VirtualChannel._(this._parent, this.id, this.stream, this.sink); @override - VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); + VirtualChannel virtualChannel([int? id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 4722aa39c6..85f9a97551 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,8 +6,8 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'src/guarantee_channel.dart'; import 'src/close_guarantee_channel.dart'; +import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -75,9 +75,9 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// - /// Unlike [new StreamChannel], this enforces the guarantees listed in the + /// Unlike [StreamChannel.new], this enforces the guarantees listed in the /// [StreamChannel] documentation. This makes it somewhat less efficient than - /// just wrapping a stream and a sink directly, so [new StreamChannel] should + /// just wrapping a stream and a sink directly, so [StreamChannel.new] should /// be used when the guarantees are provided natively. /// /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index ff6a50c681..5eb57ae410 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,16 +1,16 @@ name: stream_channel -version: 2.1.1 +version: 2.1.2-dev description: >- An abstraction for two-way communication channels based on the Dart Stream class. repository: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.14.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - lints: ^1.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 66773b59cd..28f3fee9a7 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -142,7 +142,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. final completer = Completer(); - _CloseCompleterSink(StreamSink inner) : super(inner); + _CloseCompleterSink(super.inner); @override Future close() { diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index a754421a9b..1850664cf2 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') +library; + import 'dart:async'; import 'dart:isolate'; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 763e6b8290..ee6f8d2a1e 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -348,8 +348,8 @@ void main() { group('stream channel rules', () { group('for the main stream:', () { test( - 'closing the sink causes the stream to close before it emits any more ' - 'events', () { + 'closing the sink causes the stream to close before it emits any ' + 'more events', () { channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); @@ -370,7 +370,8 @@ void main() { channel2.sink.add(3); unawaited(channel2.sink.close()); - // None of our channel.sink additions should make it to the other endpoint. + // None of our channel.sink additions should make it to the other + // endpoint. channel1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -415,8 +416,8 @@ void main() { }); test( - 'closing the sink causes the stream to close before it emits any more ' - 'events', () { + 'closing the sink causes the stream to close before it emits any ' + 'more events', () { virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); @@ -437,7 +438,8 @@ void main() { virtual2.sink.add(3); unawaited(virtual2.sink.close()); - // None of our virtual.sink additions should make it to the other endpoint. + // None of our virtual.sink additions should make it to the other + // endpoint. virtual1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); From a831fcbdbd7841a42d9d9872f705715e7797014c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:52:45 -0700 Subject: [PATCH 110/138] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/stream_channel#89) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 20b28decec..772d53beb7 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 871b223fe6c6f33594240c8942bfae7d436fc42c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:30:31 -0700 Subject: [PATCH 111/138] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/stream_channel#88) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 772d53beb7..7632673504 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 73f5b89bbbbae25455d7b366c7386063415d25f9 Mon Sep 17 00:00:00 2001 From: Tobe Osakwe Date: Tue, 11 Apr 2023 15:50:57 -0700 Subject: [PATCH 112/138] Add example/example.dart (dart-lang/stream_channel#52) --- pkgs/stream_channel/CHANGELOG.md | 1 + pkgs/stream_channel/example/example.dart | 110 +++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 pkgs/stream_channel/example/example.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0d73828395..8932188751 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.1.2-dev * Require Dart 2.19 +* Add an example. ## 2.1.1 diff --git a/pkgs/stream_channel/example/example.dart b/pkgs/stream_channel/example/example.dart new file mode 100644 index 0000000000..dd16f6750c --- /dev/null +++ b/pkgs/stream_channel/example/example.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2023, 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 'dart:convert'; +import 'dart:io'; +import 'dart:isolate'; + +import 'package:stream_channel/isolate_channel.dart'; +import 'package:stream_channel/stream_channel.dart'; + +Future main() async { + // A StreamChannel, is in simplest terms, a wrapper around a Stream and + // a StreamSink. For example, you can create a channel that wraps standard + // IO: + var stdioChannel = StreamChannel(stdin, stdout); + stdioChannel.sink.add('Hello!\n'.codeUnits); + + // Like a Stream can be transformed with a StreamTransformer, a + // StreamChannel can be transformed with a StreamChannelTransformer. + // For example, we can handle standard input as strings: + var stringChannel = stdioChannel + .transform(StreamChannelTransformer.fromCodec(utf8)) + .transformStream(LineSplitter()); + stringChannel.sink.add('world!\n'); + + // You can implement StreamChannel by extending StreamChannelMixin, but + // it's much easier to use a StreamChannelController. A controller has two + // StreamChannel members: `local` and `foreign`. The creator of a + // controller should work with the `local` channel, while the recipient should + // work with the `foreign` channel, and usually will not have direct access to + // the underlying controller. + var ctrl = StreamChannelController(); + ctrl.local.stream.listen((event) { + // Do something useful here... + }); + + // You can also pipe events from one channel to another. + ctrl + ..foreign.pipe(stringChannel) + ..local.sink.add('Piped!\n'); + await ctrl.local.sink.close(); + + // The StreamChannel interface provides several guarantees, which can be + // found here: + // https://pub.dev/documentation/stream_channel/latest/stream_channel/StreamChannel-class.html + // + // By calling `StreamChannel.withGuarantees()`, you can create a + // StreamChannel that provides all guarantees. + var dummyCtrl0 = StreamChannelController(); + var guaranteedChannel = StreamChannel.withGuarantees( + dummyCtrl0.foreign.stream, dummyCtrl0.foreign.sink); + + // To close a StreamChannel, use `sink.close()`. + await guaranteedChannel.sink.close(); + + // A MultiChannel multiplexes multiple virtual channels across a single + // underlying transport layer. For example, an application listening over + // standard I/O can still support multiple clients if it has a mechanism to + // separate events from different clients. + // + // A MultiChannel splits events into numbered channels, which are + // instances of VirtualChannel. + var dummyCtrl1 = StreamChannelController(); + var multiChannel = MultiChannel(dummyCtrl1.foreign); + var channel1 = multiChannel.virtualChannel(); + await multiChannel.sink.close(); + + // The client/peer should also create its own MultiChannel, connected to + // the underlying transport, use the corresponding ID's to handle events in + // their respective channels. It is up to you how to communicate channel ID's + // across different endpoints. + var dummyCtrl2 = StreamChannelController(); + var multiChannel2 = MultiChannel(dummyCtrl2.foreign); + var channel2 = multiChannel2.virtualChannel(channel1.id); + await channel2.sink.close(); + await multiChannel2.sink.close(); + + // Multiple instances of a Dart application can communicate easily across + // `SendPort`/`ReceivePort` pairs by means of the `IsolateChannel` class. + // Typically, one endpoint will create a `ReceivePort`, and call the + // `IsolateChannel.connectReceive` constructor. The other endpoint will be + // given the corresponding `SendPort`, and then call + // `IsolateChannel.connectSend`. + var recv = ReceivePort(); + var recvChannel = IsolateChannel.connectReceive(recv); + var sendChannel = IsolateChannel.connectSend(recv.sendPort); + + // You must manually close `IsolateChannel` sinks, however. + await recvChannel.sink.close(); + await sendChannel.sink.close(); + + // You can use the `Disconnector` transformer to cause a channel to act as + // though the remote end of its transport had disconnected. + var disconnector = Disconnector(); + var disconnectable = stringChannel.transform(disconnector); + disconnectable.sink.add('Still connected!'); + await disconnector.disconnect(); + + // Additionally: + // * The `DelegatingStreamController` class can be extended to build a + // basis for wrapping other `StreamChannel` objects. + // * The `jsonDocument` transformer converts events to/from JSON, using + // the `json` codec from `dart:convert`. + // * `package:json_rpc_2` directly builds on top of + // `package:stream_channel`, so any compatible transport can be used to + // create interactive client/server or peer-to-peer applications (i.e. + // language servers, microservices, etc. +} From 28c22df54e650925a904612e7341c255e9188000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:30:00 -0700 Subject: [PATCH 113/138] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/stream_channel#90) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 7632673504..0874bdd382 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From eedb3691c7fc61e5899c8e3cabc005dee069bf8e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:53:01 -0700 Subject: [PATCH 114/138] blast_repo fixes (dart-lang/stream_channel#91) dependabot --- pkgs/stream_channel/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 1603cdd9ee..725f03af2e 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 67ed073cbf7ef5d99011718e328bfc903ce34e14 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 20 Jun 2023 15:13:45 -0700 Subject: [PATCH 115/138] Fix a race condition in IsolateChannel.connectReceive() (dart-lang/stream_channel#92) --- pkgs/stream_channel/CHANGELOG.md | 4 +++- pkgs/stream_channel/lib/src/isolate_channel.dart | 14 ++++++++++++-- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 8 ++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8932188751..c78f64f0ee 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,9 @@ -## 2.1.2-dev +## 2.1.2 * Require Dart 2.19 * Add an example. +* Fix a race condition in `IsolateChannel.connectReceive()` where the channel + could hang forever if its sink was closed before the connection was established. ## 2.1.1 diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 55c98143f0..3fbd46d235 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -43,16 +43,26 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel.connectReceive(ReceivePort receivePort) { // We can't use a [StreamChannelCompleter] here because we need the return // value to be an [IsolateChannel]. + var isCompleted = false; var streamCompleter = StreamCompleter(); var sinkCompleter = StreamSinkCompleter(); - var channel = - IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); + + var channel = IsolateChannel._(streamCompleter.stream, sinkCompleter.sink + .transform(StreamSinkTransformer.fromHandlers(handleDone: (sink) { + if (!isCompleted) { + receivePort.close(); + streamCompleter.setSourceStream(Stream.empty()); + sinkCompleter.setDestinationSink(NullStreamSink()); + } + sink.close(); + }))); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. late StreamSubscription subscription; subscription = receivePort.listen((message) { + isCompleted = true; if (message is SendPort) { var controller = StreamChannelController(allowForeignErrors: false, sync: true); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5eb57ae410..0b4f62d4ea 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.2-dev +version: 2.1.2 description: >- An abstraction for two-way communication channels based on the Dart Stream class. diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 1850664cf2..10f1fe53ea 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -162,5 +162,13 @@ void main() { expect(connectedChannel.stream.toList(), throwsStateError); expect(connectedChannel.sink.done, completes); }); + + test('the receiving channel closes gracefully without a connection', + () async { + var connectedChannel = IsolateChannel.connectReceive(connectPort); + await connectedChannel.sink.close(); + await expectLater(connectedChannel.stream.toList(), completion(isEmpty)); + await expectLater(connectedChannel.sink.done, completes); + }); }); } From ce71194d432b609d263a6d30430117800e1392fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 03:07:24 +0000 Subject: [PATCH 116/138] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/stream_channel#93) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 0874bdd382..4c8399a816 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e98c5bac7d7af172aa40f7ddf745171af7c4bcb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 03:51:18 +0000 Subject: [PATCH 117/138] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/stream_channel#94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 4c8399a816..8b1f4d4fb7 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From d00914acc59a8f42fae5d211b06a610b9abce0c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 03:27:12 +0000 Subject: [PATCH 118/138] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/stream_channel#95) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 8b1f4d4fb7..282ba50067 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From de516dcb3999a6982670d254334b39b1e7af6589 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:14:58 -0700 Subject: [PATCH 119/138] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/stream_channel#96) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 282ba50067..367d5dea3c 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From ef684398b414ffbe6dd1bfed8a3763d9899ada3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:46:35 +0000 Subject: [PATCH 120/138] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/stream_channel#97) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 367d5dea3c..e0d4f73af8 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 913e78ca09df450843fb3de10f46fe1902d37305 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:50:53 +0000 Subject: [PATCH 121/138] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/stream_channel#98) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index e0d4f73af8..02786315a5 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 1cf10a4534934b70ecb55e442288c8471b51f9e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 03:27:16 +0000 Subject: [PATCH 122/138] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/stream_channel#99) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 02786315a5..41ca6901b0 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From c7eef23aa9b3bec0b88418612be76997136775c4 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 16 Feb 2024 16:46:43 -0800 Subject: [PATCH 123/138] blast_repo fixes (dart-lang/stream_channel#101) auto-publish, github-actions, no-response --- .../.github/workflows/no-response.yml | 37 +++++++++++++++++++ .../.github/workflows/publish.yaml | 17 +++++++++ 2 files changed, 54 insertions(+) create mode 100644 pkgs/stream_channel/.github/workflows/no-response.yml create mode 100644 pkgs/stream_channel/.github/workflows/publish.yaml diff --git a/pkgs/stream_channel/.github/workflows/no-response.yml b/pkgs/stream_channel/.github/workflows/no-response.yml new file mode 100644 index 0000000000..ab1ac49842 --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/stream_channel/.github/workflows/publish.yaml b/pkgs/stream_channel/.github/workflows/publish.yaml new file mode 100644 index 0000000000..27157a046a --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From 45fbe108fd38b1f1134b76ce85ab56b2f96d48e3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 16 Feb 2024 17:47:01 -0800 Subject: [PATCH 124/138] Require Dart 3.3, update and fix lints (dart-lang/stream_channel#100) --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 4 ++ pkgs/stream_channel/example/example.dart | 6 +-- pkgs/stream_channel/lib/src/disconnector.dart | 2 +- .../lib/src/guarantee_channel.dart | 2 +- .../lib/src/isolate_channel.dart | 2 +- .../stream_channel/lib/src/multi_channel.dart | 3 +- .../lib/src/stream_channel_completer.dart | 2 +- pkgs/stream_channel/pubspec.yaml | 6 +-- .../test/disconnector_test.dart | 16 +++---- .../test/isolate_channel_test.dart | 8 ++-- .../test/json_document_transformer_test.dart | 2 +- .../test/stream_channel_completer_test.dart | 4 +- .../test/stream_channel_test.dart | 44 +++++++++++++------ .../test/with_close_guarantee_test.dart | 2 +- .../test/with_guarantees_test.dart | 16 +++---- 16 files changed, 71 insertions(+), 50 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 41ca6901b0..db6451bcff 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.3, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index c78f64f0ee..4b8e2b54a0 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.3-wip + +* Require Dart 3.3 + ## 2.1.2 * Require Dart 2.19 diff --git a/pkgs/stream_channel/example/example.dart b/pkgs/stream_channel/example/example.dart index dd16f6750c..b41d8d94a4 100644 --- a/pkgs/stream_channel/example/example.dart +++ b/pkgs/stream_channel/example/example.dart @@ -22,7 +22,7 @@ Future main() async { // For example, we can handle standard input as strings: var stringChannel = stdioChannel .transform(StreamChannelTransformer.fromCodec(utf8)) - .transformStream(LineSplitter()); + .transformStream(const LineSplitter()); stringChannel.sink.add('world!\n'); // You can implement StreamChannel by extending StreamChannelMixin, but @@ -84,8 +84,8 @@ Future main() async { // given the corresponding `SendPort`, and then call // `IsolateChannel.connectSend`. var recv = ReceivePort(); - var recvChannel = IsolateChannel.connectReceive(recv); - var sendChannel = IsolateChannel.connectSend(recv.sendPort); + var recvChannel = IsolateChannel.connectReceive(recv); + var sendChannel = IsolateChannel.connectSend(recv.sendPort); // You must manually close `IsolateChannel` sinks, however. await recvChannel.sink.close(); diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 61969cbf8f..3414e9c775 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,7 +38,7 @@ class Disconnector implements StreamChannelTransformer { _sinks.clear(); return Future.wait(futures, eagerError: true); }); - final _disconnectMemo = AsyncMemoizer(); + final _disconnectMemo = AsyncMemoizer>(); @override StreamChannel bind(StreamChannel channel) { diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 2aa8b7b972..30ebe2ec67 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -83,7 +83,7 @@ class _GuaranteeSink implements StreamSink { @override Future get done => _doneCompleter.future; - final _doneCompleter = Completer(); + final _doneCompleter = Completer(); /// Whether connection is disconnected. /// diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 3fbd46d235..15c68a41d5 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -51,7 +51,7 @@ class IsolateChannel extends StreamChannelMixin { .transform(StreamSinkTransformer.fromHandlers(handleDone: (sink) { if (!isCompleted) { receivePort.close(); - streamCompleter.setSourceStream(Stream.empty()); + streamCompleter.setSourceStream(const Stream.empty()); sinkCompleter.setDestinationSink(NullStreamSink()); } sink.close(); diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 82f59c7c94..48942392e3 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -191,7 +191,8 @@ class _MultiChannel extends StreamChannelMixin // If the inner channel has already closed, create new virtual channels in a // closed state. if (_inner == null) { - return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); + return VirtualChannel._( + this, inputId, const Stream.empty(), NullStreamSink()); } late StreamChannelController controller; diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index 5a824c1f36..9d007eb6c8 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -34,7 +34,7 @@ class StreamChannelCompleter { /// instead contain just that error. The sink will silently discard all /// events. static StreamChannel fromFuture(Future channelFuture) { - var completer = StreamChannelCompleter(); + var completer = StreamChannelCompleter(); channelFuture.then(completer.setChannel, onError: completer.setError); return completer.channel; } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0b4f62d4ea..0cfd074a55 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,16 +1,16 @@ name: stream_channel -version: 2.1.2 +version: 2.1.3-wip description: >- An abstraction for two-way communication channels based on the Dart Stream class. repository: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.19.0 <3.0.0' + sdk: ^3.3.0 dependencies: async: ^2.5.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 28f3fee9a7..bbba568ede 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -14,8 +14,8 @@ void main() { late Disconnector disconnector; late StreamChannel channel; setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); disconnector = Disconnector(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink) @@ -52,7 +52,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -67,7 +67,7 @@ void main() { test('cancels addStream when disconnected', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); @@ -78,9 +78,9 @@ void main() { }); test('disconnect() returns the close future from the inner sink', () async { - var streamController = StreamController(); - var sinkController = StreamController(); - var disconnector = Disconnector(); + var streamController = StreamController(); + var sinkController = StreamController(); + var disconnector = Disconnector(); var sink = _CloseCompleterSink(sinkController.sink); StreamChannel.withGuarantees(streamController.stream, sink) .transform(disconnector); @@ -140,7 +140,7 @@ void main() { /// returned by [close] using [completer]. class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. - final completer = Completer(); + final completer = Completer(); _CloseCompleterSink(super.inner); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 10f1fe53ea..3a8b42e9b9 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -53,7 +53,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -109,7 +109,7 @@ void main() { test('the sink closes as soon as an error is added via addStream', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); @@ -156,7 +156,7 @@ void main() { test('the receiving channel produces an error if it gets the wrong message', () { - var connectedChannel = IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); connectPort.sendPort.send('wrong value'); expect(connectedChannel.stream.toList(), throwsStateError); @@ -165,7 +165,7 @@ void main() { test('the receiving channel closes gracefully without a connection', () async { - var connectedChannel = IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); await connectedChannel.sink.close(); await expectLater(connectedChannel.stream.toList(), completion(isEmpty)); await expectLater(connectedChannel.sink.done, completes); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 48d8f72917..290c4e2c31 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -41,6 +41,6 @@ void main() { test('synchronously throws if an unencodable object is added', () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(Object()), - throwsA(TypeMatcher())); + throwsA(const TypeMatcher())); }); } diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 22db01a760..c6fddc011c 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -14,8 +14,8 @@ void main() { late StreamChannel innerChannel; setUp(() { completer = StreamChannelCompleter(); - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 76edbdf91f..c44b6ab6f2 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -10,21 +10,17 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - late StreamController streamController; - late StreamController sinkController; - late StreamChannel channel; - setUp(() { - streamController = StreamController(); - sinkController = StreamController(); - channel = StreamChannel(streamController.stream, sinkController.sink); - }); - test("pipe() pipes data from each channel's stream into the other's sink", () { - var otherStreamController = StreamController(); - var otherSinkController = StreamController(); + var otherStreamController = StreamController(); + var otherSinkController = StreamController(); var otherChannel = StreamChannel(otherStreamController.stream, otherSinkController.sink); + + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + channel.pipe(otherChannel); streamController.add(1); @@ -41,6 +37,10 @@ void main() { }); test('transform() transforms the channel', () async { + var streamController = StreamController>(); + var sinkController = StreamController>(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel .cast>() .transform(StreamChannelTransformer.fromCodec(utf8)); @@ -59,6 +59,10 @@ void main() { }); test('transformStream() transforms only the stream', () async { + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel.cast().transformStream(const LineSplitter()); @@ -75,8 +79,12 @@ void main() { }); test('transformSink() transforms only the sink', () async { + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel.cast().transformSink( - StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); + const StreamSinkTransformer.fromStreamTransformer(LineSplitter())); streamController.add('fbl\nthp'); unawaited(streamController.close()); @@ -91,7 +99,11 @@ void main() { }); test('changeStream() changes the stream', () { - var newController = StreamController(); + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + + var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); return newController.stream; @@ -107,7 +119,11 @@ void main() { }); test('changeSink() changes the sink', () { - var newController = StreamController(); + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + + var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); return newController.sink; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index a18f09fe19..9c0b729988 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -45,7 +45,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) - .asFuture(), + .asFuture(), completes); await pumpEventQueue(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 849e304919..f026079fbb 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -12,8 +12,8 @@ void main() { late StreamController sinkController; late StreamChannel channel; setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); @@ -53,7 +53,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) - .asFuture(), + .asFuture(), completes); }); @@ -126,7 +126,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -140,8 +140,8 @@ void main() { group('with allowSinkErrors: false', () { setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink, allowSinkErrors: false); @@ -166,7 +166,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.addError('oh no'); }, count: 2)) - .asFuture(), + .asFuture(), completes); }); @@ -180,7 +180,7 @@ void main() { 'adding an error via via addStream causes the stream to emit a done ' 'event', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); From 81110f1163e86a3cc90e2632d61cf6466ea5c269 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 03:21:07 +0000 Subject: [PATCH 125/138] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/stream_channel#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index db6451bcff..b7d7d6e06e 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 9992ce8f4de7d2d7f173ea6a2cb891b4d33cd828 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 03:46:43 +0000 Subject: [PATCH 126/138] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/stream_channel#103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index b7d7d6e06e..04dbcd2b33 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.3, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 00f8ce7c416224d30500d84a88f79dcc815d7712 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:32:50 +0000 Subject: [PATCH 127/138] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/stream_channel#104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 04dbcd2b33..811bb8040e 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 9f26b26aa01b63256d2c009d92c56e1bbfc2d764 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:36:14 -0700 Subject: [PATCH 128/138] blast_repo fixes (dart-lang/stream_channel#105) dependabot --- pkgs/stream_channel/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 725f03af2e..cde02ad6a8 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From cc95d8605d58869f25768f7ad0de4643a175c6eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:38:26 +0000 Subject: [PATCH 129/138] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/stream_channel#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 811bb8040e..aad5df6f40 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 3c38e1fb8e6d286e7da04dcba4fe5f5196da5bd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 03:27:23 +0000 Subject: [PATCH 130/138] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/stream_channel#107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index aad5df6f40..77eb9e176f 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 5c400a84b384db62e5bfc3d902480079c1b8cafc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jun 2024 11:15:41 -0700 Subject: [PATCH 131/138] bump lints (dart-lang/stream_channel#108) --- pkgs/stream_channel/analysis_options.yaml | 9 --------- pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8e5d4a792b..44cda4da2b 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -3,12 +3,3 @@ include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true - -linter: - rules: - - comment_references - - always_declare_return_types - - omit_local_variable_types - - prefer_single_quotes - - unawaited_futures - - use_super_parameters diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0cfd074a55..6524721702 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -12,5 +12,5 @@ dependencies: async: ^2.5.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 - test: ^1.16.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 From 2d967e90eeb44a54405ec3c4cd51d4f563cb460e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:33:11 +0000 Subject: [PATCH 132/138] Bump the github-actions group with 2 updates (dart-lang/stream_channel#109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 77eb9e176f..9d9f1cc08f 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From c49c4109c774ec67fd1cb8828e6b2953d914a700 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 29 Jul 2024 11:27:21 -0700 Subject: [PATCH 133/138] Fix some trivial doc comment lints (dart-lang/stream_channel#110) --- pkgs/stream_channel/lib/src/stream_channel_controller.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 5c788667d3..25d5239b2b 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -2,6 +2,9 @@ // 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. +/// @docImport 'isolate_channel.dart'; +library; + import 'dart:async'; import '../stream_channel.dart'; @@ -11,7 +14,7 @@ import '../stream_channel.dart'; /// This exposes two connected [StreamChannel]s, [local] and [foreign]. The /// user's code should use [local] to emit and receive events. Then [foreign] /// can be returned for others to use. For example, here's a simplified version -/// of the implementation of [new IsolateChannel]: +/// of the implementation of [IsolateChannel.new]: /// /// ```dart /// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { From b820aeba0e772c04d0dc6c188f2814ce20996b08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 03:17:00 +0000 Subject: [PATCH 134/138] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/stream_channel#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9d9f1cc08f..30feba18cf 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From ae5aad43d700aa1689580603c55697ff864ca85b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 03:59:06 +0000 Subject: [PATCH 135/138] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/stream_channel#112) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 30feba18cf..e667e382ed 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 7808a8850caae1362e3f583eb81b34fbcb707a8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:37:21 +0000 Subject: [PATCH 136/138] Bump dart-lang/setup-dart in the github-actions group (dart-lang/stream_channel#113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index e667e382ed..c70b745e24 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.3, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 8021ff098cefbb3dec93e77a675c5db241c7bf76 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 17:01:55 +0100 Subject: [PATCH 137/138] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/stream_channel.md | 5 ++++ pkgs/stream_channel/CONTRIBUTING.md | 33 ------------------------ pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/stream_channel.md delete mode 100644 pkgs/stream_channel/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/stream_channel.md b/.github/ISSUE_TEMPLATE/stream_channel.md new file mode 100644 index 0000000000..76b5994970 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/stream_channel.md @@ -0,0 +1,5 @@ +--- +name: "package:stream_channel" +about: "Create a bug or file a feature request against package:stream_channel." +labels: "package:stream_channel" +--- \ No newline at end of file diff --git a/pkgs/stream_channel/CONTRIBUTING.md b/pkgs/stream_channel/CONTRIBUTING.md deleted file mode 100644 index 6f5e0ea67d..0000000000 --- a/pkgs/stream_channel/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 6524721702..c1b8e1f194 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -3,7 +3,7 @@ version: 2.1.3-wip description: >- An abstraction for two-way communication channels based on the Dart Stream class. -repository: https://github.com/dart-lang/stream_channel +repository: https://github.com/dart-lang/tools/tree/main/pkgs/stream_channel environment: sdk: ^3.3.0 From e66e313089cd413db345a3ab57db09da45bf2128 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 17:04:34 +0100 Subject: [PATCH 138/138] merge fixes --- .github/labeler.yml | 4 ++ .../workflows/stream_channel.yaml | 16 ++++++-- README.md | 1 + pkgs/stream_channel/.github/dependabot.yml | 15 -------- .../.github/workflows/no-response.yml | 37 ------------------- .../.github/workflows/publish.yaml | 17 --------- pkgs/stream_channel/CHANGELOG.md | 3 +- pkgs/stream_channel/README.md | 2 +- pkgs/stream_channel/pubspec.yaml | 2 +- 9 files changed, 22 insertions(+), 75 deletions(-) rename pkgs/stream_channel/.github/workflows/test-package.yml => .github/workflows/stream_channel.yaml (85%) delete mode 100644 pkgs/stream_channel/.github/dependabot.yml delete mode 100644 pkgs/stream_channel/.github/workflows/no-response.yml delete mode 100644 pkgs/stream_channel/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index eca80bbc21..ea9baeba90 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -84,6 +84,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' +'package:stream_channel': + - changed-files: + - any-glob-to-any-file: 'pkgs/stream_channel/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/.github/workflows/stream_channel.yaml similarity index 85% rename from pkgs/stream_channel/.github/workflows/test-package.yml rename to .github/workflows/stream_channel.yaml index c70b745e24..c39424dc58 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/.github/workflows/stream_channel.yaml @@ -1,17 +1,27 @@ -name: Dart CI +name: package:stream_channel on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_channel.yaml' + - 'pkgs/stream_channel/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_channel.yaml' + - 'pkgs/stream_channel/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github +defaults: + run: + working-directory: pkgs/stream_channel/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 50517c36eb..495f0ea362 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ don't naturally belong to other topic monorepos (like | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | +| [stream_channel](pkgs/stream_channel/) | An abstraction for two-way communication channels based on the Dart Stream class. | [![package issues](https://img.shields.io/badge/package:stream_channel-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Astream_channel) | [![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml deleted file mode 100644 index cde02ad6a8..0000000000 --- a/pkgs/stream_channel/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/stream_channel/.github/workflows/no-response.yml b/pkgs/stream_channel/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac49842..0000000000 --- a/pkgs/stream_channel/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/stream_channel/.github/workflows/publish.yaml b/pkgs/stream_channel/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046a..0000000000 --- a/pkgs/stream_channel/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4b8e2b54a0..30f7d32bc8 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ -## 2.1.3-wip +## 2.1.3 * Require Dart 3.3 +* Move to `dart-lang/tools` monorepo. ## 2.1.2 diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index ae1ea219d4..3677ccf5ec 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/stream_channel.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/stream_channel.yaml) [![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) [![package publisher](https://img.shields.io/pub/publisher/stream_channel.svg)](https://pub.dev/packages/stream_channel/publisher) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c1b8e1f194..eec8c1ba5c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.3-wip +version: 2.1.3 description: >- An abstraction for two-way communication channels based on the Dart Stream class.