Merge pull request #83 from dart-lang/config_specific_imports

Add `WebSocketChannel.connect` factory constructor.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbd834f..ec82a91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.1.0
+
+* Add `WebSocketChannel.connect` factory constructor supporting platform
+  independent creation of WebSockets providing the lowest common denominator
+  of support on dart:io and dart:html.
+
 ## 1.0.15
 
 * bug fix don't pass protocols parameter to WebSocket.
diff --git a/lib/src/_connect_api.dart b/lib/src/_connect_api.dart
new file mode 100644
index 0000000..93c6ce7
--- /dev/null
+++ b/lib/src/_connect_api.dart
@@ -0,0 +1,13 @@
+// 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.
+
+import '../web_socket_channel.dart';
+
+/// Creates a new WebSocket connection.
+///
+/// Connects to [uri] using and returns a channel that can be used to
+/// communicate over the resulting socket.
+WebSocketChannel connect(Uri uri) {
+  throw UnsupportedError('No implementation of the connect api provided');
+}
diff --git a/lib/src/_connect_html.dart b/lib/src/_connect_html.dart
new file mode 100644
index 0000000..3c36641
--- /dev/null
+++ b/lib/src/_connect_html.dart
@@ -0,0 +1,13 @@
+// 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.
+
+import 'package:web_socket_channel/html.dart';
+
+import '../web_socket_channel.dart';
+
+/// Creates a new WebSocket connection.
+///
+/// Connects to [uri] using and returns a channel that can be used to
+/// communicate over the resulting socket.
+WebSocketChannel connect(Uri uri) => HtmlWebSocketChannel.connect(uri);
diff --git a/lib/src/_connect_io.dart b/lib/src/_connect_io.dart
new file mode 100644
index 0000000..b788926
--- /dev/null
+++ b/lib/src/_connect_io.dart
@@ -0,0 +1,12 @@
+// 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.
+
+import '../web_socket_channel.dart';
+import '../io.dart';
+
+/// Creates a new WebSocket connection.
+///
+/// Connects to [uri] using and returns a channel that can be used to
+/// communicate over the resulting socket
+WebSocketChannel connect(Uri uri) => IOWebSocketChannel.connect(uri);
diff --git a/lib/src/channel.dart b/lib/src/channel.dart
index bbdaf34..cee27f2 100644
--- a/lib/src/channel.dart
+++ b/lib/src/channel.dart
@@ -11,6 +11,10 @@
 
 import 'copy/web_socket_impl.dart';
 
+import '_connect_api.dart'
+    if (dart.library.io) '_connect_io.dart'
+    if (dart.library.html) '_connect_html.dart' as platform;
+
 /// A [StreamChannel] that communicates over a WebSocket.
 ///
 /// This is implemented by classes that use `dart:io` and `dart:html`. The [new
@@ -94,6 +98,12 @@
       : _webSocket = WebSocketImpl.fromSocket(
             channel.stream, channel.sink, protocol, serverSide)
           ..pingInterval = pingInterval;
+
+  /// Creates a new WebSocket connection.
+  ///
+  /// Connects to [uri] using and returns a channel that can be used to
+  /// communicate over the resulting socket.
+  factory WebSocketChannel.connect(Uri uri) => platform.connect(uri);
 }
 
 /// The sink exposed by a [WebSocketChannel].
diff --git a/pubspec.yaml b/pubspec.yaml
index 71d8c19..e5a2b35 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: web_socket_channel
-version: 1.0.15
+version: 1.1.0
 
 description: >-
   StreamChannel wrappers for WebSockets. Provides a cross-platform
diff --git a/test/html_test.dart b/test/html_test.dart
index fac1e91..b05c8ec 100644
--- a/test/html_test.dart
+++ b/test/html_test.dart
@@ -79,6 +79,18 @@
     expect(await queue.next, equals([1, 2, 3, 4, 5]));
   });
 
+  test(".connect defaults to binary lists using platform independent api",
+      () async {
+    channel = WebSocketChannel.connect(Uri.parse("ws://localhost:$port"));
+
+    var queue = StreamQueue(channel.stream);
+    channel.sink.add("foo");
+    expect(await queue.next, equals("foo"));
+
+    channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
+    expect(await queue.next, equals([1, 2, 3, 4, 5]));
+  });
+
   test(".connect can use blobs", () async {
     channel = HtmlWebSocketChannel.connect("ws://localhost:$port",
         binaryType: BinaryType.blob);
diff --git a/test/io_test.dart b/test/io_test.dart
index f9032cd..4d4b1a9 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -70,6 +70,29 @@
         onDone: expectAsync0(() {}));
   });
 
+  test(".connect communicates immediately using platform independent api",
+      () async {
+    server = await HttpServer.bind("localhost", 0);
+    server.transform(WebSocketTransformer()).listen((webSocket) {
+      var channel = IOWebSocketChannel(webSocket);
+      channel.stream.listen((request) {
+        expect(request, equals("ping"));
+        channel.sink.add("pong");
+      });
+    });
+
+    var channel =
+        WebSocketChannel.connect(Uri.parse("ws://localhost:${server.port}"));
+    channel.sink.add("ping");
+
+    channel.stream.listen(
+        expectAsync1((message) {
+          expect(message, equals("pong"));
+          channel.sink.close(5678, "raisin");
+        }, count: 1),
+        onDone: expectAsync0(() {}));
+  });
+
   test(".connect with an immediate call to close", () async {
     server = await HttpServer.bind("localhost", 0);
     server.transform(WebSocketTransformer()).listen((webSocket) {