Version 2.14.0-186.0.dev

Merge commit '4d0fb34272be75e6fd40fafa73507546a002ad6d' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
index 1390395..09be91b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
@@ -54,23 +54,6 @@
         // ignore: unnecessary_null_comparison
         assert(isUnresolvedIdentifier != null);
 
-  @Deprecated('Use the default constructor')
-  const ErrorCode.temporary2({
-    String? correction,
-    bool hasPublishedDocs = false,
-    bool isUnresolvedIdentifier = false,
-    required String message,
-    required String name,
-    required String uniqueName,
-  }) : this(
-          correction: correction,
-          hasPublishedDocs: hasPublishedDocs,
-          isUnresolvedIdentifier: isUnresolvedIdentifier,
-          message: message,
-          name: name,
-          uniqueName: uniqueName,
-        );
-
   /**
    * The template used to create the correction to be displayed for this error,
    * or `null` if there is no correction information for this error. The
diff --git a/pkg/analysis_server/analysis_options.yaml b/pkg/analysis_server/analysis_options.yaml
index 06e8506..90f1d22 100644
--- a/pkg/analysis_server/analysis_options.yaml
+++ b/pkg/analysis_server/analysis_options.yaml
@@ -17,6 +17,7 @@
   rules:
     - await_only_futures
     - avoid_single_cascade_in_expression_statements
+    - depend_on_referenced_packages
     - empty_statements
     - iterable_contains_unrelated_type
     - list_remove_unrelated_type
diff --git a/pkg/analysis_server_client/analysis_options.yaml b/pkg/analysis_server_client/analysis_options.yaml
index fd37fb4..e4fce7e 100644
--- a/pkg/analysis_server_client/analysis_options.yaml
+++ b/pkg/analysis_server_client/analysis_options.yaml
@@ -5,6 +5,7 @@
 linter:
   rules:
     - await_only_futures
+    - depend_on_referenced_packages
     - empty_statements
     - unnecessary_brace_in_string_interps
     #
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 9996e7f..1d8a622 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -30,6 +30,7 @@
     - avoid_dynamic_calls
     - avoid_unused_constructor_parameters
     - await_only_futures
+    - depend_on_referenced_packages
     - empty_statements
     - iterable_contains_unrelated_type
     - list_remove_unrelated_type
diff --git a/pkg/analyzer_cli/analysis_options.yaml b/pkg/analyzer_cli/analysis_options.yaml
index e69ac71..069c2d2 100644
--- a/pkg/analyzer_cli/analysis_options.yaml
+++ b/pkg/analyzer_cli/analysis_options.yaml
@@ -11,6 +11,7 @@
 linter:
   rules:
     avoid_unused_constructor_parameters: true
+    depend_on_referenced_packages: true
     directives_ordering: true
 
     # We import heavily from package:analyzer/src.
diff --git a/pkg/analyzer_plugin/analysis_options.yaml b/pkg/analyzer_plugin/analysis_options.yaml
index ac616cb..c183e26 100644
--- a/pkg/analyzer_plugin/analysis_options.yaml
+++ b/pkg/analyzer_plugin/analysis_options.yaml
@@ -4,6 +4,7 @@
 linter:
   rules:
     - await_only_futures
+    - depend_on_referenced_packages
     - empty_statements
     - unnecessary_brace_in_string_interps
     #
diff --git a/pkg/dartdev/analysis_options.yaml b/pkg/dartdev/analysis_options.yaml
index 5168988..b5b7736 100644
--- a/pkg/dartdev/analysis_options.yaml
+++ b/pkg/dartdev/analysis_options.yaml
@@ -13,6 +13,7 @@
 linter:
   rules:
     - always_declare_return_types
+    - depend_on_referenced_packages
     - directives_ordering
     - overridden_fields
     - prefer_single_quotes
diff --git a/runtime/bin/file_system_watcher.cc b/runtime/bin/file_system_watcher.cc
index a32d62b..66e55b5 100644
--- a/runtime/bin/file_system_watcher.cc
+++ b/runtime/bin/file_system_watcher.cc
@@ -14,6 +14,8 @@
 namespace dart {
 namespace bin {
 
+bool FileSystemWatcher::delayed_filewatch_callback_ = false;
+
 void FUNCTION_NAME(FileSystemWatcher_IsSupported)(Dart_NativeArguments args) {
   Dart_SetBooleanReturnValue(args, FileSystemWatcher::IsSupported());
 }
diff --git a/runtime/bin/file_system_watcher.h b/runtime/bin/file_system_watcher.h
index c9a54e7..364c608 100644
--- a/runtime/bin/file_system_watcher.h
+++ b/runtime/bin/file_system_watcher.h
@@ -48,7 +48,15 @@
   static intptr_t GetSocketId(intptr_t id, intptr_t path_id);
   static Dart_Handle ReadEvents(intptr_t id, intptr_t path_id);
 
+  static void set_delayed_filewatch_callback(bool value) {
+    delayed_filewatch_callback_ = value;
+  }
+  static bool delayed_filewatch_callback() {
+    return delayed_filewatch_callback_;
+  }
+
  private:
+  static bool delayed_filewatch_callback_;
   DISALLOW_COPY_AND_ASSIGN(FileSystemWatcher);
 };
 
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 88d6986..2cde121 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -61,7 +61,6 @@
          int write_fd,
          bool recursive)
         : watcher_(watcher),
-          ready_(false),
           base_path_length_(strlen(base_path)),
           path_ref_(CFStringCreateWithCString(NULL,
                                               base_path,
@@ -74,9 +73,14 @@
     }
 
     ~Node() {
-      Stop();
+      // This is invoked outside of [Callback] execution because
+      // [context.release] callback is invoked when [FSEventStream] is
+      // deallocated, the same [FSEventStream] that [Callback] gets a reference
+      // to during its execution. [Callback] holding a reference prevents stream
+      // from deallocation.
       close(write_fd_);
       CFRelease(path_ref_);
+      watcher_ = nullptr;  // this is to catch access-after-free in Callback
     }
 
     void set_ref(FSEventStreamRef ref) { ref_ = ref; }
@@ -85,6 +89,9 @@
       FSEventStreamContext context;
       memset(&context, 0, sizeof(context));
       context.info = reinterpret_cast<void*>(this);
+      context.release = [](const void* info) {
+        delete static_cast<const Node*>(info);
+      };
       CFArrayRef array = CFArrayCreate(
           NULL, reinterpret_cast<const void**>(&path_ref_), 1, NULL);
       FSEventStreamRef ref = FSEventStreamCreate(
@@ -93,7 +100,6 @@
       CFRelease(array);
 
       set_ref(ref);
-      ready_.store(true, std::memory_order_release);
 
       FSEventStreamScheduleWithRunLoop(ref_, watcher_->run_loop_,
                                        kCFRunLoopDefaultMode);
@@ -103,15 +109,12 @@
     }
 
     void Stop() {
-      ASSERT(ready_);
       FSEventStreamStop(ref_);
       FSEventStreamInvalidate(ref_);
       FSEventStreamRelease(ref_);
-      ready_.store(false, std::memory_order_release);
     }
 
     FSEventsWatcher* watcher() const { return watcher_; }
-    bool ready() const { return ready_.load(std::memory_order_acquire); }
     intptr_t base_path_length() const { return base_path_length_; }
     int read_fd() const { return read_fd_; }
     int write_fd() const { return write_fd_; }
@@ -119,7 +122,6 @@
 
    private:
     FSEventsWatcher* watcher_;
-    std::atomic<bool> ready_;
     intptr_t base_path_length_;
     CFStringRef path_ref_;
     int read_fd_;
@@ -218,12 +220,15 @@
                        void* event_paths,
                        const FSEventStreamEventFlags event_flags[],
                        const FSEventStreamEventId event_ids[]) {
-    Node* node = reinterpret_cast<Node*>(client);
+    if (FileSystemWatcher::delayed_filewatch_callback()) {
+      // Used in tests to highlight race between callback invocation
+      // and unwatching the file path, Node destruction
+      TimerUtils::Sleep(1000 /* ms */);
+    }
+    Node* node = static_cast<Node*>(client);
+    RELEASE_ASSERT(node->watcher() != nullptr);
     ASSERT(Thread::Compare(node->watcher()->threadId_,
                            Thread::GetCurrentThreadId()));
-    if (!node->ready()) {
-      return;
-    }
     for (size_t i = 0; i < num_events; i++) {
       char* path = reinterpret_cast<char**>(event_paths)[i];
       FSEvent event;
@@ -274,7 +279,7 @@
 
 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
   USE(id);
-  delete reinterpret_cast<FSEventsWatcher::Node*>(path_id);
+  reinterpret_cast<FSEventsWatcher::Node*>(path_id)->Stop();
 }
 
 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 157b70f..dd82f2d 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -10,6 +10,7 @@
 
 #include "bin/dartdev_isolate.h"
 #include "bin/error_exit.h"
+#include "bin/file_system_watcher.h"
 #include "bin/options.h"
 #include "bin/platform.h"
 #include "bin/utils.h"
@@ -483,6 +484,9 @@
       Options::bypass_trusting_system_roots());
 #endif  // !defined(DART_IO_SECURE_SOCKET_DISABLED)
 
+  FileSystemWatcher::set_delayed_filewatch_callback(
+      Options::delayed_filewatch_callback());
+
   // The arguments to the VM are at positions 1 through i-1 in argv.
   Platform::SetExecutableArguments(i, argv);
 
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index a0fc972..4fab09c 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -49,7 +49,8 @@
   V(enable_service_port_fallback, enable_service_port_fallback)                \
   V(disable_dart_dev, disable_dart_dev)                                        \
   V(long_ssl_cert_evaluation, long_ssl_cert_evaluation)                        \
-  V(bypass_trusting_system_roots, bypass_trusting_system_roots)
+  V(bypass_trusting_system_roots, bypass_trusting_system_roots)                \
+  V(delayed_filewatch_callback, delayed_filewatch_callback)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 9eab978..1ba9c22 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -127,7 +127,8 @@
     // isolate_ was set as side effect of create callback.
     ASSERT(KernelIsolate::IsKernelIsolate(isolate));
 
-    isolate->message_handler()->Run(Dart::thread_pool(), NULL, ShutdownIsolate,
+    isolate->message_handler()->Run(isolate->group()->thread_pool(), NULL,
+                                    ShutdownIsolate,
                                     reinterpret_cast<uword>(isolate));
   }
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 07e58ba..c243b02b 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -389,7 +389,8 @@
       return;
     }
 
-    isolate->message_handler()->Run(Dart::thread_pool(), NULL, ShutdownIsolate,
+    isolate->message_handler()->Run(isolate->group()->thread_pool(), NULL,
+                                    ShutdownIsolate,
                                     reinterpret_cast<uword>(isolate));
   }
 
diff --git a/tests/standalone/io/file_system_watcher_large_set_test.dart b/tests/standalone/io/file_system_watcher_large_set_test.dart
new file mode 100644
index 0000000..0f010cf
--- /dev/null
+++ b/tests/standalone/io/file_system_watcher_large_set_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, 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.
+
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
+
+// Verifies that cancelling subscription from inside of the event handler
+// works as expected, does not result in crash or hang.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart";
+
+final completer = Completer<void>();
+late StreamSubscription subscription;
+
+void handleWatchEvent(event) {
+  if (event is FileSystemCreateEvent && event.path.endsWith('txt')) {
+    subscription.cancel();
+    completer.complete();
+  }
+}
+
+void main() async {
+  if (!FileSystemEntity.isWatchSupported) return;
+  final dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  final watcher = dir.watch();
+  subscription = watcher.listen(handleWatchEvent);
+
+  print('watching ${dir.path}');
+  for (int i = 0; i < 1000; i++) {
+    File(join(dir.path, 'file_$i.txt')).createSync();
+  }
+  await completer.future;
+  try {
+    dir.deleteSync(recursive: true);
+  } catch (_) {}
+}
diff --git a/tests/standalone/string_overflow_test.dart b/tests/standalone/string_overflow_test.dart
index 5de5d71..d63a5b1 100644
--- a/tests/standalone/string_overflow_test.dart
+++ b/tests/standalone/string_overflow_test.dart
@@ -4,13 +4,21 @@
 
 // Test to ensure that the VM does not have an integer overflow issue
 // when concatenating strings.
+// See https://github.com/dart-lang/sdk/issues/11214
 
 import "package:expect/expect.dart";
 
 main() {
   String a = "a";
-  for (; a.length < 256 * 1024 * 1024;) a = a + a;
 
-  var concat = "$a$a$a$a$a$a$a$a";
-  Expect.equals(concat.length, 2147483648);
+  var caughtOutOfMemoryException = false;
+  try {
+    while (true) {
+      a = "$a$a$a$a$a$a$a$a";
+    }
+  } on OutOfMemoryError {
+    caughtOutOfMemoryException = true;
+  }
+  Expect.isTrue(caughtOutOfMemoryException);
+  Expect.isTrue(a.startsWith('aaaaa') && a.length > 1024);
 }
diff --git a/tests/standalone_2/io/file_system_watcher_large_set_test.dart b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
new file mode 100644
index 0000000..9b3e290
--- /dev/null
+++ b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, 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.
+
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
+
+// Verifies that cancelling subscription from inside of the event handler
+// works as expected, does not result in crash or hang.
+
+import "dart:async";
+import "dart:io";
+
+import "package:path/path.dart";
+
+final completer = Completer<void>();
+var subscription;
+
+void handleWatchEvent(event) {
+  if (event is FileSystemCreateEvent && event.path.endsWith('txt')) {
+    subscription.cancel();
+    completer.complete();
+  }
+}
+
+void main() async {
+  if (!FileSystemEntity.isWatchSupported) return;
+  final dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  final watcher = dir.watch();
+  subscription = watcher.listen(handleWatchEvent);
+
+  print('watching ${dir.path}');
+  for (int i = 0; i < 1000; i++) {
+    File(join(dir.path, 'file_$i.txt')).createSync();
+  }
+  await completer.future;
+  try {
+    dir.deleteSync(recursive: true);
+  } catch (_) {}
+}
diff --git a/tests/standalone_2/string_overflow_test.dart b/tests/standalone_2/string_overflow_test.dart
index 070a7e5..17cd32d 100644
--- a/tests/standalone_2/string_overflow_test.dart
+++ b/tests/standalone_2/string_overflow_test.dart
@@ -6,13 +6,21 @@
 
 // Test to ensure that the VM does not have an integer overflow issue
 // when concatenating strings.
+// See https://github.com/dart-lang/sdk/issues/11214
 
 import "package:expect/expect.dart";
 
 main() {
   String a = "a";
-  for (; a.length < 256 * 1024 * 1024;) a = a + a;
 
-  var concat = "$a$a$a$a$a$a$a$a";
-  Expect.equals(concat.length, 2147483648);
+  var caughtOutOfMemoryException = false;
+  try {
+    while (true) {
+      a = "$a$a$a$a$a$a$a$a";
+    }
+  } on OutOfMemoryError {
+    caughtOutOfMemoryException = true;
+  }
+  Expect.isTrue(caughtOutOfMemoryException);
+  Expect.isTrue(a.startsWith('aaaaa') && a.length > 1024);
 }
diff --git a/tools/VERSION b/tools/VERSION
index 4152226..6c40680 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 185
+PRERELEASE 186
 PRERELEASE_PATCH 0
\ No newline at end of file