Version 2.12.0-4.0.dev

Merge commit '65b424b3fd72302709d6507c0d51651d58d520fa' into 'dev'
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bfaf1df..9d133af 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -262,6 +262,47 @@
     return []
 
 
+def _CheckTestPlan(input_api, output_api):
+    """Run test plan check.
+
+  Each change that touches specified directories in the checkout are required
+  to have TEST= line explaining how this change was validated.
+  """
+
+    DIRS = [
+        'runtime/vm',
+        'runtime/bin',
+        'runtime/lib',
+        'runtime/include',
+        'runtime/observatory',
+        'runtime/observatory_2',
+        'runtime/platform',
+        'pkg/vm',
+        'sdk/lib/_internal/vm',
+    ]
+
+    # Run only if directory was affected.
+    files = [f.LocalPath() for f in input_api.AffectedFiles()]
+    affected = filter(lambda dir: any(f.startswith(dir) for f in files), DIRS)
+    if len(affected) != 0 and input_api.change.tags.get('TEST', '') == '':
+        return [
+            output_api.PresubmitError('Change is missing TEST= line',
+                                      long_text="""
+When changing files in one of the following directories you
+must include TEST= line at the end of your change description.
+
+    %s
+
+This line is expected to explain in a free form the kind of testing
+that was performed to validate effect of the change. For example,
+it can list newly added tests or already existing tests which are assumed
+to cover the change.
+""" % ('    '.join(affected)))
+        ]
+
+    return []
+
+
 def _CheckClangTidy(input_api, output_api):
     """Run clang-tidy on VM changes."""
 
@@ -333,6 +374,7 @@
     results.extend(_CheckLayering(input_api, output_api))
     results.extend(_CheckClangTidy(input_api, output_api))
     results.extend(_CheckTestMatrixValid(input_api, output_api))
+    results.extend(_CheckTestPlan(input_api, output_api))
     results.extend(
         input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
     return results
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart b/pkg/front_end/testcases/nnbd/issue42607.dart
new file mode 100644
index 0000000..91f7d49
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, 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.
+
+// @dart = 2.6
+
+test() {
+  int x = 3;
+  x?.isEven;
+  x = null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.outline.expect
new file mode 100644
index 0000000..67a3569
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42607.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart = 2.6
+// ^^^^^^^^^^^^^^
+//
+import self as self;
+
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.strong.expect
new file mode 100644
index 0000000..f1a2bdd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42607.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart = 2.6
+// ^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  core::int* x = 3;
+  let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::bool*} null : #t1.{core::int::isEven};
+  x = null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.strong.transformed.expect
new file mode 100644
index 0000000..f1a2bdd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42607.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart = 2.6
+// ^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  core::int* x = 3;
+  let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::bool*} null : #t1.{core::int::isEven};
+  x = null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline.expect
new file mode 100644
index 0000000..5cf5db8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+// @dart = 2.6
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..94295cd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+// @dart = 2.6
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.weak.expect
new file mode 100644
index 0000000..2678d44
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.weak.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  core::int* x = 3;
+  let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::bool*} null : #t1.{core::int::isEven};
+  x = null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42607.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42607.dart.weak.transformed.expect
new file mode 100644
index 0000000..2678d44
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42607.dart.weak.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  core::int* x = 3;
+  let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::bool*} null : #t1.{core::int::isEven};
+  x = null;
+}
+static method main() → dynamic {}
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index afd7f11..ecd4c97 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -337,7 +337,7 @@
    * Increasing the length fails if the element type does not allow `null`.
    *
    * Throws an [UnsupportedError] if the list is fixed-length or
-   * if attempting tp enlarge the list when `null` is not a valid element.
+   * if attempting to enlarge the list when `null` is not a valid element.
    */
   set length(int newLength);
 
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 2fdfc3e..8eb32b2 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -6,6 +6,10 @@
 LibTest/core/Uri/hasEmptyPath_A01_t01: RuntimeError
 LibTest/core/Uri/parse_A05_t01: RuntimeError
 
+[ $system == windows ]
+LibTest/io/Stdin/readByteSync_A01_t01: Skip # Issue 43645
+LibTest/io/Stdin/readByteSync_A01_t02: Skip # Issue 43645
+
 [ $arch == simarm64 && $runtime == dart_precompiled ]
 LibTest/async/Stream/Stream.periodic_all_t02: Skip # Issue 42898
 
diff --git a/tests/co19_2/co19_2-runtime.status b/tests/co19_2/co19_2-runtime.status
index 26ee4d3..4246d55 100644
--- a/tests/co19_2/co19_2-runtime.status
+++ b/tests/co19_2/co19_2-runtime.status
@@ -6,6 +6,9 @@
 LibTest/core/Uri/hasEmptyPath_A01_t01: RuntimeError
 LibTest/core/Uri/parse_A05_t01: RuntimeError
 
+[ $system == windows ]
+LibTest/io/ProcessResult/exitCode_A01_t02: Skip # Issue 43645
+
 [ $compiler != dart2js && $runtime != none && $runtime != vm && !$checked ]
 LibTest/async/Future/catchError_A03_t05: RuntimeError
 
diff --git a/tools/VERSION b/tools/VERSION
index 535cc4c..7858ce1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 3
+PRERELEASE 4
 PRERELEASE_PATCH 0
\ No newline at end of file