Version 2.10.0-142.0.dev

Merge commit 'ac6095a7cc5098d4449db9eb7f2a41da6f76d00e' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 86ed829..5e44eee 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1116,7 +1116,8 @@
 
     Future<void> compute(CorrectionProducer producer) async {
       producer.configure(context);
-      var builder = ChangeBuilder(workspace: context.workspace);
+      var builder = ChangeBuilder(
+          workspace: context.workspace, eol: context.utils.endOfLine);
       await producer.compute(builder);
       _addFixFromBuilder(builder, producer.fixKind,
           args: producer.fixArguments);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
index 6bb0fd9..5103e74 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
@@ -197,6 +197,34 @@
 ''');
   }
 
+  Future<void> test_lineEndings() async {
+    // TODO(dantup): Remove the need for this here, and have all of the tests
+    // test with CRLF when running on Windows.
+    final newlineWithoutCarriageReturn = RegExp(r'(?<!\r)\n');
+    String asCrLf(String input) =>
+        input.replaceAll(newlineWithoutCarriageReturn, '\r\n');
+    await resolveTestUnit(asCrLf('''
+class A {
+  void ma() {}
+}
+
+class B implements A {
+}
+'''));
+    await assertHasFix(asCrLf('''
+class A {
+  void ma() {}
+}
+
+class B implements A {
+  @override
+  void ma() {
+    // TODO: implement ma
+  }
+}
+'''));
+  }
+
   Future<void> test_mergeToField_getterSetter() async {
     await resolveTestUnit('''
 class A {
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 62f4670..b269720 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -28,6 +28,9 @@
   rules:
     - avoid_unused_constructor_parameters
     - empty_statements
+    - iterable_contains_unrelated_type
+    - list_remove_unrelated_type
     - prefer_typing_uninitialized_variables
     - unnecessary_brace_in_string_interps
+    - unnecessary_overrides
     - unnecessary_parenthesis
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index a469a99..ecf68fe 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3321,11 +3321,6 @@
   }
 
   @override
-  set accessors(List<PropertyAccessorElement> accessors) {
-    super.accessors = accessors;
-  }
-
-  @override
   List<InterfaceType> get allSupertypes => <InterfaceType>[supertype];
 
   @override
@@ -3378,11 +3373,6 @@
   }
 
   @override
-  set fields(List<FieldElement> fields) {
-    super.fields = fields;
-  }
-
-  @override
   bool get hasNonFinalField => false;
 
   @override
@@ -3838,11 +3828,6 @@
   ElementKind get kind => ElementKind.EXPORT;
 
   @override
-  set metadata(List<ElementAnnotation> metadata) {
-    super.metadata = metadata;
-  }
-
-  @override
   int get nameOffset {
     if (linkedNode != null) {
       return linkedContext.getDirectiveOffset(linkedNode);
@@ -4917,11 +4902,6 @@
   ElementKind get kind => ElementKind.IMPORT;
 
   @override
-  set metadata(List<ElementAnnotation> metadata) {
-    super.metadata = metadata;
-  }
-
-  @override
   int get nameOffset {
     if (linkedNode != null) {
       return linkedContext.getDirectiveOffset(linkedNode);
@@ -4985,11 +4965,6 @@
   }
 
   @override
-  set uri(String uri) {
-    super.uri = uri;
-  }
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitImportElement(this);
 
   @override
@@ -6248,11 +6223,6 @@
     return super.hasImplicitType;
   }
 
-  @override
-  set hasImplicitType(bool hasImplicitType) {
-    super.hasImplicitType = hasImplicitType;
-  }
-
   bool get hasInitializer {
     return linkedNode != null && linkedContext.hasInitializer(linkedNode);
   }
@@ -6406,11 +6376,6 @@
     return super.hasImplicitType;
   }
 
-  @override
-  set hasImplicitType(bool hasImplicitType) {
-    super.hasImplicitType = hasImplicitType;
-  }
-
   /// True if this parameter inherits from a covariant parameter. This happens
   /// when it overrides a method in a supertype that has a corresponding
   /// covariant parameter.
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index 1a4ba96..f9f9e2e 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -833,11 +833,6 @@
   }
 
   @override
-  void setUp() {
-    super.setUp();
-  }
-
-  @override
   void verifyCreatedCollection() {
     super.verifyCreatedCollection();
     assertPackageBuildWorkspaceFor(testFilePath);
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index c16d12f..ed00442 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -23,7 +23,7 @@
 
   /// The end-of-line marker used in the file being edited, or `null` if the
   /// default marker should be used.
-  String eol;
+  final String eol;
 
   /// A table mapping group ids to the associated linked edit groups.
   final Map<String, LinkedEditGroup> _linkedEditGroups =
@@ -49,7 +49,8 @@
   /// Initialize a newly created change builder. If the builder will be used to
   /// create changes for Dart files, then either a [session] or a [workspace]
   /// must be provided (but not both).
-  ChangeBuilderImpl({AnalysisSession session, ChangeWorkspace workspace})
+  ChangeBuilderImpl(
+      {AnalysisSession session, ChangeWorkspace workspace, this.eol})
       : assert(session == null || workspace == null),
         workspace = workspace ?? _SingleSessionWorkspace(session);
 
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
index 0d0914f..0d310b5 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
@@ -16,8 +16,10 @@
   /// Initialize a newly created change builder. If the builder will be used to
   /// create changes for Dart files, then either a [session] or a [workspace]
   /// must be provided (but not both).
-  factory ChangeBuilder({AnalysisSession session, ChangeWorkspace workspace}) =
-      ChangeBuilderImpl;
+  factory ChangeBuilder(
+      {AnalysisSession session,
+      ChangeWorkspace workspace,
+      String eol}) = ChangeBuilderImpl;
 
   /// Return the range of the selection for the change being built, or `null` if
   /// there is no selection.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index c31e1a2c..72c1210 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -4885,13 +4885,13 @@
                                      OneByteString::InstanceSize(length),
                                      is_canonical);
       str->ptr()->length_ = Smi::New(length);
-      uint32_t hash = 0;
+      StringHasher hasher;
       for (intptr_t j = 0; j < length; j++) {
-        uint8_t code_point = d->Read<uint8_t>();
-        str->ptr()->data()[j] = code_point;
-        hash = CombineHashes(hash, code_point);
+        uint8_t code_unit = d->Read<uint8_t>();
+        str->ptr()->data()[j] = code_unit;
+        hasher.Add(code_unit);
       }
-      String::SetCachedHash(str, FinalizeHash(hash, String::kHashBits));
+      String::SetCachedHash(str, hasher.Finalize());
     }
   }
 };
@@ -4964,9 +4964,14 @@
                                      TwoByteString::InstanceSize(length),
                                      is_canonical);
       str->ptr()->length_ = Smi::New(length);
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(str->ptr()->data());
-      d->ReadBytes(cdata, length * 2);
-      String::SetCachedHash(str, String::Hash(str));
+      StringHasher hasher;
+      for (intptr_t j = 0; j < length; j++) {
+        uint16_t code_unit = d->Read<uint8_t>();
+        code_unit = code_unit | (d->Read<uint8_t>() << 8);
+        str->ptr()->data()[j] = code_unit;
+        hasher.Add(code_unit);
+      }
+      String::SetCachedHash(str, hasher.Finalize());
     }
   }
 };
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index e81f325..119901a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -21734,25 +21734,6 @@
   return buffer;
 }
 
-// Synchronize with implementation in compiler (intrinsifier).
-class StringHasher : ValueObject {
- public:
-  StringHasher() : hash_(0) {}
-  void Add(int32_t ch) { hash_ = CombineHashes(hash_, ch); }
-  void Add(const String& str, intptr_t begin_index, intptr_t len);
-
-  // Return a non-zero hash of at most 'bits' bits.
-  intptr_t Finalize(int bits) {
-    ASSERT(1 <= bits && bits <= (kBitsPerWord - 1));
-    hash_ = FinalizeHash(hash_, bits);
-    ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
-    return hash_;
-  }
-
- private:
-  uint32_t hash_;
-};
-
 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) {
   ASSERT(begin_index >= 0);
   ASSERT(len >= 0);
@@ -21762,48 +21743,32 @@
   }
   if (str.IsOneByteString()) {
     NoSafepointScope no_safepoint;
-    uint8_t* str_addr = OneByteString::CharAddr(str, begin_index);
-    for (intptr_t i = 0; i < len; i++) {
-      Add(*str_addr);
-      str_addr++;
-    }
+    Add(OneByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsExternalOneByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(ExternalOneByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsTwoByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(TwoByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsExternalOneByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(ExternalTwoByteString::CharAddr(str, begin_index), len);
   } else {
-    String::CodePointIterator it(str, begin_index, len);
-    while (it.Next()) {
-      Add(it.Current());
-    }
+    UNREACHABLE();
   }
 }
 
 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
   StringHasher hasher;
   hasher.Add(str, begin_index, len);
-  return hasher.Finalize(kHashBits);
+  return hasher.Finalize();
 }
 
 intptr_t String::HashConcat(const String& str1, const String& str2) {
-  intptr_t len1 = str1.Length();
-  // Since String::Hash works at the code point (rune) level, a surrogate pair
-  // that crosses the boundary between str1 and str2 must be composed.
-  if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) {
-    const String& temp = String::Handle(String::Concat(str1, str2));
-    return temp.Hash();
-  } else {
-    StringHasher hasher;
-    hasher.Add(str1, 0, len1);
-    hasher.Add(str2, 0, str2.Length());
-    return hasher.Finalize(kHashBits);
-  }
-}
-
-template <typename T>
-static intptr_t HashImpl(const T* characters, intptr_t len) {
-  ASSERT(len >= 0);
   StringHasher hasher;
-  for (intptr_t i = 0; i < len; i++) {
-    hasher.Add(characters[i]);
-  }
-  return hasher.Finalize(String::kHashBits);
+  hasher.Add(str1, 0, str1.Length());
+  hasher.Add(str2, 0, str2.Length());
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(StringPtr raw) {
@@ -21833,24 +21798,21 @@
 }
 
 intptr_t String::Hash(const char* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  StringHasher hasher;
+  hasher.Add(reinterpret_cast<const uint8_t*>(characters), len);
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(const uint8_t* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  StringHasher hasher;
+  hasher.Add(characters, len);
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
   StringHasher hasher;
-  intptr_t i = 0;
-  while (i < len) {
-    hasher.Add(Utf16::Next(characters, &i, len));
-  }
-  return hasher.Finalize(kHashBits);
-}
-
-intptr_t String::Hash(const int32_t* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  hasher.Add(characters, len);
+  return hasher.Finalize();
 }
 
 intptr_t String::CharSize() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 46144d1b..b14b8e9 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -9065,6 +9065,32 @@
   friend class Pass2Visitor;                // Stack "handle"
 };
 
+// Synchronize with implementation in compiler (intrinsifier).
+class StringHasher : ValueObject {
+ public:
+  StringHasher() : hash_(0) {}
+  void Add(uint16_t code_unit) { hash_ = CombineHashes(hash_, code_unit); }
+  void Add(const uint8_t* code_units, intptr_t len) {
+    while (len > 0) {
+      Add(*code_units);
+      code_units++;
+      len--;
+    }
+  }
+  void Add(const uint16_t* code_units, intptr_t len) {
+    while (len > 0) {
+      Add(LoadUnaligned(code_units));
+      code_units++;
+      len--;
+    }
+  }
+  void Add(const String& str, intptr_t begin_index, intptr_t len);
+  intptr_t Finalize() { return FinalizeHash(hash_, String::kHashBits); }
+
+ private:
+  uint32_t hash_;
+};
+
 class OneByteString : public AllStatic {
  public:
   static uint16_t CharAt(const String& str, intptr_t index) {
@@ -9327,6 +9353,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
 };
@@ -9424,6 +9451,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
   friend class Utf8;
@@ -9518,6 +9546,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
 };
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 66adb2f..e1118e2 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -1338,7 +1338,7 @@
   const String& clef = String::Handle(String::FromUTF16(clef_utf16, 2));
   int32_t clef_utf32[] = {0x1D11E};
   EXPECT(clef.Equals(clef_utf32, 1));
-  intptr_t hash32 = String::Hash(clef_utf32, 1);
+  intptr_t hash32 = String::Hash(String::FromUTF32(clef_utf32, 1));
   EXPECT_EQ(hash32, clef.Hash());
   EXPECT_EQ(hash32, String::HashConcat(
                         String::Handle(String::FromUTF16(clef_utf16, 1)),
@@ -1817,7 +1817,8 @@
   uint16_t char16[] = {'E', 'l', 'f'};
   String& elf1 = String::Handle(Symbols::FromUTF16(thread, char16, 3));
   int32_t char32[] = {'E', 'l', 'f'};
-  String& elf2 = String::Handle(Symbols::FromUTF32(thread, char32, 3));
+  String& elf2 = String::Handle(
+      Symbols::New(thread, String::Handle(String::FromUTF32(char32, 3))));
   EXPECT(elf1.IsSymbol());
   EXPECT(elf2.IsSymbol());
   EXPECT_EQ(elf1.raw(), Symbols::New(thread, "Elf"));
@@ -1832,13 +1833,14 @@
   EXPECT_EQ(monkey.raw(), Symbols::New(thread, monkey_utf8));
 
   int32_t kMonkeyFace = 0x1f435;
-  String& monkey2 = String::Handle(Symbols::FromCharCode(thread, kMonkeyFace));
+  String& monkey2 = String::Handle(
+      Symbols::New(thread, String::Handle(String::FromUTF32(&kMonkeyFace, 1))));
   EXPECT_EQ(monkey.raw(), monkey2.raw());
 
   // Unicode cat face with tears of joy.
   int32_t kCatFaceWithTearsOfJoy = 0x1f639;
-  String& cat =
-      String::Handle(Symbols::FromCharCode(thread, kCatFaceWithTearsOfJoy));
+  String& cat = String::Handle(Symbols::New(
+      thread, String::Handle(String::FromUTF32(&kCatFaceWithTearsOfJoy, 1))));
 
   uint16_t cat_utf16[] = {0xd83d, 0xde39};
   String& cat2 = String::Handle(Symbols::FromUTF16(thread, cat_utf16, 2));
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 10424d1..4fb75a0 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -44,10 +44,6 @@
   return String::FromUTF16(data, len, space);
 }
 
-StringPtr StringFrom(const int32_t* data, intptr_t len, Heap::Space space) {
-  return String::FromUTF32(data, len, space);
-}
-
 template <typename CharType>
 class CharArray {
  public:
@@ -76,7 +72,6 @@
 };
 typedef CharArray<uint8_t> Latin1Array;
 typedef CharArray<uint16_t> UTF16Array;
-typedef CharArray<int32_t> UTF32Array;
 
 class StringSlice {
  public:
@@ -481,12 +476,6 @@
   return NewSymbol(thread, UTF16Array(utf16_array, len));
 }
 
-StringPtr Symbols::FromUTF32(Thread* thread,
-                             const int32_t* utf32_array,
-                             intptr_t len) {
-  return NewSymbol(thread, UTF32Array(utf32_array, len));
-}
-
 StringPtr Symbols::FromConcat(Thread* thread,
                               const String& str1,
                               const String& str2) {
@@ -586,7 +575,7 @@
   }
 }
 
-// StringType can be StringSlice, ConcatString, or {Latin1,UTF16,UTF32}Array.
+// StringType can be StringSlice, ConcatString, or {Latin1,UTF16}Array.
 template <typename StringType>
 StringPtr Symbols::NewSymbol(Thread* thread, const StringType& str) {
   REUSABLE_OBJECT_HANDLESCOPE(thread);
@@ -782,9 +771,9 @@
   return Symbols::New(thread, buffer);
 }
 
-StringPtr Symbols::FromCharCode(Thread* thread, int32_t char_code) {
+StringPtr Symbols::FromCharCode(Thread* thread, uint16_t char_code) {
   if (char_code > kMaxOneCharCodeSymbol) {
-    return FromUTF32(thread, &char_code, 1);
+    return FromUTF16(thread, &char_code, 1);
   }
   return predefined_[char_code];
 }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 80d6da1..df2a0f0 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -680,11 +680,6 @@
                              const uint16_t* utf16_array,
                              intptr_t len);
 
-  // Creates a new Symbol from an array of UTF-32 encoded characters.
-  static StringPtr FromUTF32(Thread* thread,
-                             const int32_t* utf32_array,
-                             intptr_t len);
-
   static StringPtr New(Thread* thread, const String& str);
   static StringPtr New(Thread* thread,
                        const String& str,
@@ -712,7 +707,7 @@
   // Returns char* of predefined symbol.
   static const char* Name(SymbolId symbol);
 
-  static StringPtr FromCharCode(Thread* thread, int32_t char_code);
+  static StringPtr FromCharCode(Thread* thread, uint16_t char_code);
 
   static StringPtr* PredefinedAddress() {
     return reinterpret_cast<StringPtr*>(&predefined_);
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 0d888f2..abd886f 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -576,255 +576,149 @@
   }
 
   static Future<ConnectionTask<_NativeSocket>> startConnect(
-      dynamic host, int port, dynamic sourceAddress) async {
+      dynamic host, int port, dynamic sourceAddress) {
     if (host is String) {
       host = escapeLinkLocalAddress(host);
     }
     _throwOnBadPort(port);
-    if (sourceAddress is String) {
-      sourceAddress = InternetAddress(sourceAddress);
-    } else if (sourceAddress != null && sourceAddress is! _InternetAddress) {
-      throw ArgumentError(
-          'sourceAddress $sourceAddress must be either String or InternetAddress');
+    if (sourceAddress != null && sourceAddress is! _InternetAddress) {
+      if (sourceAddress is String) {
+        sourceAddress = new InternetAddress(sourceAddress);
+      }
     }
+    return new Future.value(host).then((host) {
+      if (host is _InternetAddress) return [host];
+      return lookup(host).then((addresses) {
+        if (addresses.isEmpty) {
+          throw createError(null, "Failed host lookup: '$host'");
+        }
+        return addresses;
+      });
+    }).then((addresses) {
+      var completer = new Completer<_NativeSocket>();
+      var it = (addresses as List<InternetAddress>).iterator;
+      var error = null;
+      var connecting = new HashMap();
 
-    // The stream containing Internet addresses
-    final stream = await _lookup(host);
-    var streamSubscription;
-    final completer = Completer<_NativeSocket>();
-    // The first error that occurs.
-    var error = null;
-    // The map contains currently attempted connections.
-    final connecting = HashMap<_NativeSocket, Timer>();
-    // A queue contains Internet addresses that waits for connecting.
-    // `stream` keeps pushing element into queue, and connectNext() consume
-    // them.
-    final queue = <InternetAddress>[];
-    // The flag that stream of addresses is done.
-    var streamClosed = false;
-    // connectNext() will exhaust all elements from the queue. In the case of an
-    // element taking so long that connectNext() has finished trying all
-    // addresses, an explicit call to connectNext() is needed to restart the
-    // process.
-    var tryConnect = true;
-
-    // It will try each element in the `queue` to establish the connection.
-    // There can be multiple Internet addresses are under processing. Whenever
-    // a connection is successfully established (by receiving a write event),
-    // all pending connections stored in the `connecting` will be cancelled.
-    //
-    // 1. Check the status of `queue`, `completer` and `connecting`.
-    //      Return an error if all elements have been tried.
-    //      Reset tryConnect so that next element will be examined if `stream`
-    //      is still open.
-    // 2. Create a socket.
-    //      Try next address by issuing another connectNext() if this failed and
-    //      keep the first error.
-    // 3. Register a timer, if socket creation succeeds, to try next address.
-    // 4. Set up a handler for socket. It will cancel all other pending
-    //    connections and timers if it succeeds. Otherwise, keep the first
-    //    error and issue connectNext().
-    void connectNext() {
-      if (completer.isCompleted) return;
-      if (queue.isEmpty) {
-        if (streamClosed && connecting.isEmpty) {
-          assert(error != null);
-          completer.completeError(error);
-        } else if (!streamClosed) {
-          // If new addresses comes after all elements in the queue have been
-          // processed, issue another connectNext().
-          tryConnect = true;
-        }
-        return;
-      }
-      final _InternetAddress address = queue.removeAt(0) as _InternetAddress;
-      var socket = _NativeSocket.normal(address);
-      var result;
-      if (sourceAddress == null) {
-        if (address.type == InternetAddressType.unix) {
-          result = socket.nativeCreateUnixDomainConnect(
-              address.address, _Namespace._namespace);
-        } else {
-          result = socket.nativeCreateConnect(
-              address._in_addr, port, address._scope_id);
-        }
-      } else {
-        assert(sourceAddress is _InternetAddress);
-        if (address.type == InternetAddressType.unix) {
-          assert(sourceAddress.type == InternetAddressType.unix);
-          result = socket.nativeCreateUnixDomainBindConnect(
-              address.address, sourceAddress.address, _Namespace._namespace);
-        } else {
-          result = socket.nativeCreateBindConnect(address._in_addr, port,
-              sourceAddress._in_addr, address._scope_id);
-        }
-      }
-      if (result is OSError) {
-        // Keep first error, if present.
-        if (error == null) {
-          int errorCode = result.errorCode;
-          if (sourceAddress != null &&
-              errorCode != null &&
-              socket.isBindError(errorCode)) {
-            error = createError(result, "Bind failed", sourceAddress);
-          } else {
-            error = createError(result, "Connection failed", address, port);
+      void connectNext() {
+        if (!it.moveNext()) {
+          if (connecting.isEmpty) {
+            assert(error != null);
+            completer.completeError(error);
           }
-        }
-        connectNext();
-      } else {
-        // Query the local port for error messages.
-        try {
-          socket.port;
-        } catch (e) {
-          error ??= createError(e, "Connection failed", address, port);
-          connectNext();
           return;
         }
-        // Set up timer for when we should retry the next address
-        // (if any).
-        final duration =
-            address.isLoopback ? _retryDurationLoopback : _retryDuration;
-        final timer = Timer(duration, connectNext);
-        setupResourceInfo(socket);
-
-        connecting[socket] = timer;
-        // Setup handlers for receiving the first write event which
-        // indicate that the socket is fully connected.
-        socket.setHandlers(write: () {
-          timer.cancel();
-          connecting.remove(socket);
-          // From 'man 2 connect':
-          // After select(2) indicates writability, use getsockopt(2) to read
-          // the SO_ERROR option at level SOL_SOCKET to determine whether
-          // connect() completed successfully (SO_ERROR is zero) or
-          // unsuccessfully.
-          OSError osError = socket.nativeGetError();
-          if (osError.errorCode != 0) {
-            socket.close();
-            error ??= osError;
-            // No timer is active for triggering next tryConnect(), do it
-            // manually.
-            if (connecting.isEmpty) connectNext();
-            return;
+        final _InternetAddress address = it.current as _InternetAddress;
+        var socket = new _NativeSocket.normal(address);
+        var result;
+        if (sourceAddress == null) {
+          if (address.type == InternetAddressType.unix) {
+            result = socket.nativeCreateUnixDomainConnect(
+                address.address, _Namespace._namespace);
+          } else {
+            result = socket.nativeCreateConnect(
+                address._in_addr, port, address._scope_id);
           }
-          socket.setListening(read: false, write: false);
-          completer.complete(socket);
-          connecting.forEach((s, t) {
-            t.cancel();
-            s.close();
-            s.setHandlers();
-            s.setListening(read: false, write: false);
-          });
-          connecting.clear();
-        }, error: (e, st) {
-          timer.cancel();
-          socket.close();
+        } else {
+          assert(sourceAddress is _InternetAddress);
+          if (address.type == InternetAddressType.unix) {
+            assert(sourceAddress.type == InternetAddressType.unix);
+            result = socket.nativeCreateUnixDomainBindConnect(
+                address.address, sourceAddress.address, _Namespace._namespace);
+          } else {
+            result = socket.nativeCreateBindConnect(address._in_addr, port,
+                sourceAddress._in_addr, address._scope_id);
+          }
+        }
+        if (result is OSError) {
           // Keep first error, if present.
-          error ??= e;
-          connecting.remove(socket);
-          if (connecting.isEmpty) connectNext();
-        });
-        socket.setListening(read: false, write: true);
-      }
-    }
-
-    void onCancel() {
-      connecting.forEach((s, t) {
-        t.cancel();
-        s.close();
-        s.setHandlers();
-        s.setListening(read: false, write: false);
-        if (error == null) {
-          error = createError(null,
-              "Connection attempt cancelled, host: ${host}, port: ${port}");
-        }
-      });
-      connecting.clear();
-      if (!completer.isCompleted) {
-        completer.completeError(error! as Object);
-      }
-    }
-
-    // The stream is constructed in the _lookup() and should not emit the error.
-    streamSubscription = stream.listen((address) {
-      queue.add(address);
-      if (tryConnect) {
-        tryConnect = false;
-        connectNext();
-      }
-    }, onError: (e) {
-      streamSubscription.cancel();
-      streamClosed = true;
-      // The error comes from lookup() and we just rethrow the error.
-      throw e;
-    }, onDone: () {
-      streamClosed = true;
-      // In case that stream closes later than connectNext() exhausts all
-      // Internet addresses, check whether an error is thrown.
-      if (queue.isEmpty && connecting.isEmpty && !completer.isCompleted) {
-        completer.completeError(error);
-      }
-    });
-
-    return Future.value(
-        ConnectionTask<_NativeSocket>._(completer.future, onCancel));
-  }
-
-  // The [host] should be either a String or an _InternetAddress.
-  static Future<Stream> _lookup(host) async {
-    if (host is _InternetAddress) {
-      return Stream.value(host);
-    } else {
-      assert(host is String);
-      // If host is an IPv4 or IPv6 literal, bypass the lookup.
-      final inAddr = _InternetAddress._parse(host);
-      if (inAddr != null && inAddr.length == _InternetAddress._IPv4AddrLength) {
-        var addresses = await lookup(host, type: InternetAddressType.IPv4);
-        if (addresses.isEmpty) {
-          throw createError(null, "Failed host lookup: '$host'");
-        }
-        return Stream.fromIterable(addresses);
-      }
-      if (inAddr != null && inAddr.length == _InternetAddress._IPv6AddrLength) {
-        var addresses = await lookup(host, type: InternetAddressType.IPv6);
-        if (addresses.isEmpty) {
-          throw createError(null, "Failed host lookup: '$host'");
-        }
-        return Stream.fromIterable(addresses);
-      }
-
-      if (Platform.isIOS) {
-        return _concurrentLookup(host);
-      } else {
-        var addresses = await lookup(host, type: InternetAddressType.any);
-        if (addresses.isEmpty) {
-          throw createError(null, "Failed host lookup: '$host'");
-        }
-        return Stream.fromIterable(addresses);
-      }
-    }
-  }
-
-  static Stream<InternetAddress> _concurrentLookup(String host) {
-    final controller = StreamController<InternetAddress>();
-    // Lookup IPv4 and IPv6 concurrently
-    Future.wait([
-      for (final type in [InternetAddressType.IPv4, InternetAddressType.IPv6])
-        lookup(host, type: type).then((list) {
-          for (final address in list) {
-            controller.add(address);
+          if (error == null) {
+            int errorCode = result.errorCode;
+            if (sourceAddress != null &&
+                errorCode != null &&
+                socket.isBindError(errorCode)) {
+              error = createError(result, "Bind failed", sourceAddress);
+            } else {
+              error = createError(result, "Connection failed", address, port);
+            }
           }
-          return list.isNotEmpty;
-        })
-    ]).then((successes) {
-      if (!successes.contains(true)) {
-        // Neither lookup found an address.
-        throw createError(null, "Failed host lookup: '$host'");
+          connectNext();
+        } else {
+          // Query the local port for error messages.
+          try {
+            socket.port;
+          } catch (e) {
+            if (error == null) {
+              error = createError(e, "Connection failed", address, port);
+            }
+            connectNext();
+          }
+          // Set up timer for when we should retry the next address
+          // (if any).
+          var duration =
+              address.isLoopback ? _retryDurationLoopback : _retryDuration;
+          var timer = new Timer(duration, connectNext);
+          setupResourceInfo(socket);
+
+          connecting[socket] = timer;
+          // Setup handlers for receiving the first write event which
+          // indicate that the socket is fully connected.
+          socket.setHandlers(write: () {
+            timer.cancel();
+            connecting.remove(socket);
+            // From 'man 2 connect':
+            // After select(2) indicates writability, use getsockopt(2) to read
+            // the SO_ERROR option at level SOL_SOCKET to determine whether
+            // connect() completed successfully (SO_ERROR is zero) or
+            // unsuccessfully.
+            OSError osError = socket.nativeGetError();
+            if (osError.errorCode != 0) {
+              socket.close();
+              if (error == null) error = osError;
+              if (connecting.isEmpty) connectNext();
+              return;
+            }
+            socket.setListening(read: false, write: false);
+            completer.complete(socket);
+            connecting.forEach((s, t) {
+              t.cancel();
+              s.close();
+              s.setHandlers();
+              s.setListening(read: false, write: false);
+            });
+            connecting.clear();
+          }, error: (e, st) {
+            timer.cancel();
+            socket.close();
+            // Keep first error, if present.
+            if (error == null) error = e;
+            connecting.remove(socket);
+            if (connecting.isEmpty) connectNext();
+          });
+          socket.setListening(read: false, write: true);
+        }
       }
-      controller.close();
+
+      void onCancel() {
+        connecting.forEach((s, t) {
+          t.cancel();
+          s.close();
+          s.setHandlers();
+          s.setListening(read: false, write: false);
+          if (error == null) {
+            error = createError(null,
+                "Connection attempt cancelled, host: ${host}, port: ${port}");
+          }
+        });
+        connecting.clear();
+        if (!completer.isCompleted) {
+          completer.completeError(error);
+        }
+      }
+
+      connectNext();
+      return new ConnectionTask<_NativeSocket>._(completer.future, onCancel);
     });
-    return controller.stream;
   }
 
   static Future<_NativeSocket> connect(
diff --git a/tools/VERSION b/tools/VERSION
index 047c185..7869782 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 141
+PRERELEASE 142
 PRERELEASE_PATCH 0
\ No newline at end of file