Version 2.14.0-188.5.beta

* Cherry-pick 5f8a9d33d2f81c8ff7714c03c473b1291823403b to beta
* Cherry-pick fb32ffd97f365bc4c286b506d9be272a794345f5 to beta
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 00d1c06..cadd093 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -154,12 +154,15 @@
   }
 
   bool _keepAnnotation(Expression annotation) {
-    final constant = (annotation as ConstantExpression).constant;
-    if (constant is InstanceConstant) {
-      final cls = constant.classNode;
-      return (cls == externalNameClass) ||
-          (cls == pragmaClass) ||
-          (protobufHandler != null && protobufHandler.usesAnnotationClass(cls));
+    if (annotation is ConstantExpression) {
+      final constant = annotation.constant;
+      if (constant is InstanceConstant) {
+        final cls = constant.classNode;
+        return (cls == externalNameClass) ||
+            (cls == pragmaClass) ||
+            (protobufHandler != null &&
+                protobufHandler.usesAnnotationClass(cls));
+      }
     }
     return false;
   }
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index 87e9d66..8564aa6 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -314,6 +314,15 @@
 
 #endif  // defined(TARGET_OS_LINUX)
 
+// Restore default SIGPIPE handler, which is only needed on mac
+// since that is the only platform we explicitly ignore it.
+// See Platform::Initialize() in platform_macos.cc.
+DART_EXPORT void RestoreSIGPIPEHandler() {
+#if defined(HOST_OS_MACOS)
+  signal(SIGPIPE, SIG_DFL);
+#endif
+}
+
 DART_EXPORT void IGH_MsanUnpoison(void* start, intptr_t length) {
   MSAN_UNPOISON(start, length);
 }
@@ -418,7 +427,7 @@
 
 #define FATAL(error) Fatal(__FILE__, __LINE__, error)
 
-void SleepOnAnyOS(intptr_t seconds) {
+DART_EXPORT void SleepOnAnyOS(intptr_t seconds) {
 #if defined(HOST_OS_WINDOWS)
   Sleep(1000 * seconds);
 #else
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 8c6be8b..f9e00c2 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -44,6 +44,11 @@
     FDUtils::SaveErrorAndClose(fd);
     return -1;
   }
+  // Don't raise SIGPIPE when attempting to write to a connection which has
+  // already closed.
+  int optval = 1;
+  VOID_NO_RETRY_EXPECTED(
+      setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)));
   return fd;
 }
 
diff --git a/tests/standalone/io/socket_sigpipe_test.dart b/tests/standalone/io/socket_sigpipe_test.dart
new file mode 100644
index 0000000..ec6f5c8
--- /dev/null
+++ b/tests/standalone/io/socket_sigpipe_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2021, 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.
+//
+// Tests that SIGPIPE won't terminate websocket client dart app.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import 'package:ffi/ffi.dart';
+import 'package:path/path.dart' as p;
+
+import '../../../tests/ffi/dylib_utils.dart';
+
+class Isolate extends Opaque {}
+
+abstract class FfiBindings {
+  static final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+  static final RestoreSIGPIPEHandler =
+      ffiTestFunctions.lookupFunction<Void Function(), void Function()>(
+          "RestoreSIGPIPEHandler");
+  static final SleepOnAnyOS = ffiTestFunctions.lookupFunction<
+      Void Function(IntPtr), void Function(int)>("SleepOnAnyOS");
+}
+
+Future<void> main() async {
+  asyncStart();
+
+  final server = await Process.start(Platform.executable, <String>[
+    p.join(p.dirname(Platform.script.toFilePath()),
+        "socket_sigpipe_test_server.dart")
+  ]);
+  final serverPort = Completer<int>();
+  server.stdout
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((line) {
+    print('server stdout: $line');
+    if (!serverPort.isCompleted) {
+      serverPort.complete(int.parse(line));
+    }
+  });
+  server.stderr
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((data) {
+    print('server stderr: $data');
+  });
+
+  FfiBindings.RestoreSIGPIPEHandler();
+  final ws =
+      await WebSocket.connect('ws://localhost:${await serverPort.future}');
+  ws.listen((var data) {
+    print('Got $data');
+    // Sleep to prevent closed socket events coming through and being handled.
+    // This way websocket stays open and writing into it should trigger SIGPIPE.
+    // Unless of course we requested SIGPIPE not to be generated on broken socket
+    // pipe. This is what this test is testing - that the SIGPIPE is not generated
+    // on broken socket pipe.
+    ws.add('foo');
+    FfiBindings.SleepOnAnyOS(10 /*seconds*/); // give server time to exit
+    ws.add('baz');
+    ws.close();
+  }, onDone: () {
+    asyncEnd();
+  }, onError: (e, st) {
+    Expect.fail('Client websocket failed $e $st');
+  });
+}
diff --git a/tests/standalone/io/socket_sigpipe_test_server.dart b/tests/standalone/io/socket_sigpipe_test_server.dart
new file mode 100644
index 0000000..89265af
--- /dev/null
+++ b/tests/standalone/io/socket_sigpipe_test_server.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, 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.
+//
+// Helper server program for socket_sigpipe_test.dart
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    print(server.port);
+    server.listen((request) {
+      WebSocketTransformer.upgrade(request).then((websocket) async {
+        websocket.add('bar');
+        await websocket.close();
+        await server.close();
+        print('closed');
+      });
+    });
+  });
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 3c981bc..d299104 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -47,6 +47,7 @@
 [ $runtime == dart_precompiled ]
 http_launch_test: Skip
 io/addlatexhash_test: Skip
+io/socket_sigpipe_test: SkipByDesign # Spawns server process using Platform.executable
 io/wait_for_event_isolate_test: SkipByDesign # Uses mirrors.
 io/wait_for_event_microtask_test: SkipByDesign # Uses mirrors.
 io/wait_for_event_nested_microtask_test: SkipByDesign # Uses mirrors.
diff --git a/tests/standalone_2/io/socket_sigpipe_test.dart b/tests/standalone_2/io/socket_sigpipe_test.dart
new file mode 100644
index 0000000..ec6f5c8
--- /dev/null
+++ b/tests/standalone_2/io/socket_sigpipe_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2021, 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.
+//
+// Tests that SIGPIPE won't terminate websocket client dart app.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import 'package:ffi/ffi.dart';
+import 'package:path/path.dart' as p;
+
+import '../../../tests/ffi/dylib_utils.dart';
+
+class Isolate extends Opaque {}
+
+abstract class FfiBindings {
+  static final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+  static final RestoreSIGPIPEHandler =
+      ffiTestFunctions.lookupFunction<Void Function(), void Function()>(
+          "RestoreSIGPIPEHandler");
+  static final SleepOnAnyOS = ffiTestFunctions.lookupFunction<
+      Void Function(IntPtr), void Function(int)>("SleepOnAnyOS");
+}
+
+Future<void> main() async {
+  asyncStart();
+
+  final server = await Process.start(Platform.executable, <String>[
+    p.join(p.dirname(Platform.script.toFilePath()),
+        "socket_sigpipe_test_server.dart")
+  ]);
+  final serverPort = Completer<int>();
+  server.stdout
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((line) {
+    print('server stdout: $line');
+    if (!serverPort.isCompleted) {
+      serverPort.complete(int.parse(line));
+    }
+  });
+  server.stderr
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((data) {
+    print('server stderr: $data');
+  });
+
+  FfiBindings.RestoreSIGPIPEHandler();
+  final ws =
+      await WebSocket.connect('ws://localhost:${await serverPort.future}');
+  ws.listen((var data) {
+    print('Got $data');
+    // Sleep to prevent closed socket events coming through and being handled.
+    // This way websocket stays open and writing into it should trigger SIGPIPE.
+    // Unless of course we requested SIGPIPE not to be generated on broken socket
+    // pipe. This is what this test is testing - that the SIGPIPE is not generated
+    // on broken socket pipe.
+    ws.add('foo');
+    FfiBindings.SleepOnAnyOS(10 /*seconds*/); // give server time to exit
+    ws.add('baz');
+    ws.close();
+  }, onDone: () {
+    asyncEnd();
+  }, onError: (e, st) {
+    Expect.fail('Client websocket failed $e $st');
+  });
+}
diff --git a/tests/standalone_2/io/socket_sigpipe_test_server.dart b/tests/standalone_2/io/socket_sigpipe_test_server.dart
new file mode 100644
index 0000000..89265af
--- /dev/null
+++ b/tests/standalone_2/io/socket_sigpipe_test_server.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, 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.
+//
+// Helper server program for socket_sigpipe_test.dart
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    print(server.port);
+    server.listen((request) {
+      WebSocketTransformer.upgrade(request).then((websocket) async {
+        websocket.add('bar');
+        await websocket.close();
+        await server.close();
+        print('closed');
+      });
+    });
+  });
+}
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index df81919..702d8e9 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -47,6 +47,7 @@
 [ $runtime == dart_precompiled ]
 http_launch_test: Skip
 io/addlatexhash_test: Skip
+io/socket_sigpipe_test: SkipByDesign # Spawns server process using Platform.executable
 io/wait_for_event_isolate_test: SkipByDesign # Uses mirrors.
 io/wait_for_event_microtask_test: SkipByDesign # Uses mirrors.
 io/wait_for_event_nested_microtask_test: SkipByDesign # Uses mirrors.
diff --git a/tools/VERSION b/tools/VERSION
index d2adf79..f9064bf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 14
 PATCH 0
 PRERELEASE 188
-PRERELEASE_PATCH 3
\ No newline at end of file
+PRERELEASE_PATCH 5
\ No newline at end of file