Version 2.14.0-60.0.dev

Merge commit 'b88a5d05f89b3b078baf6bfc63d6c74b48fe5bdf' into 'dev'
diff --git a/pkg/front_end/test/crashing_test_case_minimizer.dart b/pkg/front_end/test/crashing_test_case_minimizer.dart
index 57c27f6..3460433 100644
--- a/pkg/front_end/test/crashing_test_case_minimizer.dart
+++ b/pkg/front_end/test/crashing_test_case_minimizer.dart
@@ -58,6 +58,8 @@
           settings.targetString = "flutter";
         } else if (arg.startsWith("--target=ddc")) {
           settings.targetString = "ddc";
+        } else if (arg.startsWith("--target=dart2js")) {
+          settings.targetString = "dart2js";
         } else if (arg == "--noTryToDeleteEmptyFilesUpFront") {
           settings.noTryToDeleteEmptyFilesUpFront = true;
         } else if (arg.startsWith("--wantErrorOnReload=")) {
diff --git a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart b/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
index 46a2b61..db1d9dcc 100644
--- a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
+++ b/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
@@ -25,6 +25,8 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
+import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
+
 import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
@@ -1652,7 +1654,8 @@
     Uint8List candidate = builder.takeBytes();
     if (candidate.length == data.length) return;
 
-    if (!_parsesWithoutError(candidate, _isUriNnbd(uri))) {
+    if (uri.path.endsWith(".dart") &&
+        !_parsesWithoutError(candidate, _isUriNnbd(uri))) {
       print("WARNING: Parser error after stuff at ${StackTrace.current}");
     }
 
@@ -1941,6 +1944,9 @@
       case "ddc":
         target = new DevCompilerTarget(targetFlags);
         break;
+      case "dart2js":
+        target = new Dart2jsTarget("dart2js", targetFlags);
+        break;
       default:
         throw "Unknown target '$target'";
     }
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index 5c535ba..9792678 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -15,6 +15,8 @@
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
+import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
+
 import "package:dev_compiler/src/kernel/target.dart" show DevCompilerTarget;
 
 import 'package:expect/expect.dart' show Expect;
@@ -32,7 +34,7 @@
     show ProcessedOptions;
 
 import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
+    show computePlatformBinariesLocation, computePlatformDillName;
 
 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
 
@@ -213,7 +215,8 @@
           "target",
           "forceLateLoweringForTesting",
           "trackWidgetCreation",
-          "incrementalSerialization"
+          "incrementalSerialization",
+          "nnbdMode",
         ]);
         result = await new NewWorldTest().newWorldTest(
           data,
@@ -225,6 +228,7 @@
           map["forceLateLoweringForTesting"] ?? false,
           map["trackWidgetCreation"] ?? false,
           map["incrementalSerialization"],
+          map["nnbdMode"] == "strong" ? NnbdMode.Strong : NnbdMode.Weak,
         );
         break;
       default:
@@ -390,7 +394,8 @@
       String targetName,
       bool forceLateLoweringForTesting,
       bool trackWidgetCreation,
-      bool incrementalSerialization) async {
+      bool incrementalSerialization,
+      NnbdMode nnbdMode) async {
     final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
 
     TargetFlags targetFlags = new TargetFlags(
@@ -398,13 +403,13 @@
             forceLateLoweringForTesting ? LateLowering.all : LateLowering.none,
         trackWidgetCreation: trackWidgetCreation);
     Target target = new VmTarget(targetFlags);
-    String sdkSummary = "vm_platform_strong.dill";
     if (targetName != null) {
       if (targetName == "None") {
         target = new NoneTarget(targetFlags);
       } else if (targetName == "DDC") {
         target = new DevCompilerTarget(targetFlags);
-        sdkSummary = "ddc_platform.dill";
+      } else if (targetName == "dart2js") {
+        target = new Dart2jsTarget("dart2js", targetFlags);
       } else if (targetName == "VM") {
         // default.
       } else {
@@ -412,6 +417,12 @@
       }
     }
 
+    String sdkSummary = computePlatformDillName(
+        target,
+        nnbdMode,
+        () => throw new UnsupportedError(
+            "No platform dill for target '${targetName}' with $nnbdMode."));
+
     final Uri base = Uri.parse("org-dartlang-test:///");
     final Uri sdkSummaryUri = base.resolve(sdkSummary);
     final Uri initializeFrom = base.resolve("initializeFrom.dill");
@@ -525,6 +536,7 @@
 
       if (brandNewWorld) {
         options = getOptions(target: target, sdkSummary: sdkSummary);
+        options.nnbdMode = nnbdMode;
         options.fileSystem = fs;
         options.sdkRoot = null;
         options.sdkSummary = sdkSummaryUri;
@@ -549,6 +561,8 @@
             ExperimentalFlag.nonNullable: false
           };
         }
+        // A separate "world" can also change nnbd mode ---
+        // notice that the platform is not updated though!
         if (world["nnbdMode"] != null) {
           String nnbdMode = world["nnbdMode"];
           switch (nnbdMode) {
diff --git a/pkg/front_end/testcases/incremental/can_get_rid_of_nnbd_issue_error.yaml b/pkg/front_end/testcases/incremental/can_get_rid_of_nnbd_issue_error.yaml
index e20ec17..b877600 100644
--- a/pkg/front_end/testcases/incremental/can_get_rid_of_nnbd_issue_error.yaml
+++ b/pkg/front_end/testcases/incremental/can_get_rid_of_nnbd_issue_error.yaml
@@ -6,10 +6,10 @@
 # to get rid of it if the error is fixed.
 
 type: newworld
+nnbdMode: strong
 worlds:
   - entry: package:baz/main.dart
     experiments: non-nullable
-    nnbdMode: strong
     errors: true
     sources:
       .dart_tool/package_config.json: |
@@ -54,7 +54,6 @@
   # Update "nothing" so we still want the error.
   - entry: package:baz/main.dart
     experiments: non-nullable
-    nnbdMode: strong
     worldType: updated
     expectInitializeFromDill: false
     errors: true
@@ -76,7 +75,6 @@
   # Update ONE package to be strong.
   - entry: package:baz/main.dart
     experiments: non-nullable
-    nnbdMode: strong
     worldType: updated
     expectInitializeFromDill: false
     errors: true
@@ -114,7 +112,6 @@
   # Update the last package to be strong.
   - entry: package:baz/main.dart
     experiments: non-nullable
-    nnbdMode: strong
     worldType: updated
     expectInitializeFromDill: false
     errors: false
diff --git a/pkg/front_end/testcases/incremental/dart2js_late.yaml b/pkg/front_end/testcases/incremental/dart2js_late.yaml
new file mode 100644
index 0000000..d7d761c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/dart2js_late.yaml
@@ -0,0 +1,34 @@
+# 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.md file.
+
+# Reproduce a compilation failure: After invalidation it no longer compiles.
+# Dart2js doesn't really use the incremental compiler though.
+
+type: newworld
+target: dart2js
+worlds:
+  - entry: late_statics.dart
+    experiments: non-nullable
+    sources:
+      late_statics.dart: |
+        import 'late_statics_lib.dart' as lib;
+        void testUninitializedNonFinalTopLevelField() {
+          print(lib.a);
+          lib.a = 42;
+          print(lib.a);
+        }
+      late_statics_lib.dart: |
+        late int a;
+    expectedLibraryCount: 2
+
+  - entry: late_statics.dart
+    worldType: updated
+    errors: true # (currently?) dart2js changes the interface and doesn't have the setter anymore. dartbug.com/45854
+    experiments: non-nullable
+    expectInitializeFromDill: false
+    invalidate:
+      - late_statics.dart
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: false
+
diff --git a/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.1.expect b/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.1.expect
new file mode 100644
index 0000000..efbafde
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.1.expect
@@ -0,0 +1,15 @@
+main = <No Member>;
+library from "org-dartlang-test:///late_statics.dart" as lat {
+
+  import "org-dartlang-test:///late_statics_lib.dart" as lib;
+
+  static method testUninitializedNonFinalTopLevelField() → void {
+    dart.core::print(lat2::a.{_late_helper::_Cell::readField}<dart.core::int>(){() → dart.core::int});
+    lat2::a.{_late_helper::_Cell::value} = 42;
+    dart.core::print(lat2::a.{_late_helper::_Cell::readField}<dart.core::int>(){() → dart.core::int});
+  }
+}
+library from "org-dartlang-test:///late_statics_lib.dart" as lat2 {
+
+  static final field _late_helper::_Cell a = new _late_helper::_Cell::•();
+}
diff --git a/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.2.expect b/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.2.expect
new file mode 100644
index 0000000..5398173
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/dart2js_late.yaml.world.2.expect
@@ -0,0 +1,22 @@
+main = <No Member>;
+library from "org-dartlang-test:///late_statics.dart" as lat {
+//
+// Problems in library:
+//
+// org-dartlang-test:///late_statics.dart:4:7: Error: Setter not found: 'a'.
+//   lib.a = 42;
+//       ^
+//
+
+  import "org-dartlang-test:///late_statics_lib.dart" as lib;
+
+  static method testUninitializedNonFinalTopLevelField() → void {
+    dart.core::print(lat2::a);
+    invalid-expression "org-dartlang-test:///late_statics.dart:4:7: Error: Setter not found: 'a'.\n  lib.a = 42;\n      ^";
+    dart.core::print(lat2::a);
+  }
+}
+library from "org-dartlang-test:///late_statics_lib.dart" as lat2 {
+
+  static final field _late_helper::_Cell a = new _late_helper::_Cell::•();
+}
diff --git a/pkg/front_end/testcases/incremental/issue_42323.yaml b/pkg/front_end/testcases/incremental/issue_42323.yaml
index 0b2d164..747acd6 100644
--- a/pkg/front_end/testcases/incremental/issue_42323.yaml
+++ b/pkg/front_end/testcases/incremental/issue_42323.yaml
@@ -9,10 +9,10 @@
 # See https://github.com/dart-lang/sdk/issues/42323.
 
 type: newworld
+nnbdMode: strong
 worlds:
   - entry: bin/runMe.dart
     experiments: non-nullable
-    nnbdMode: strong
     enableStringReplacement: true
     sources:
       .dart_tool/package_config.json: |
diff --git a/pkg/front_end/testcases/incremental/issue_42323_prime.yaml b/pkg/front_end/testcases/incremental/issue_42323_prime.yaml
index 59e9a32..97d90ab 100644
--- a/pkg/front_end/testcases/incremental/issue_42323_prime.yaml
+++ b/pkg/front_end/testcases/incremental/issue_42323_prime.yaml
@@ -9,10 +9,10 @@
 # Good "variant" of https://github.com/dart-lang/sdk/issues/42323.
 
 type: newworld
+nnbdMode: strong
 worlds:
   - entry: bin/runMe.dart
     experiments: non-nullable
-    nnbdMode: strong
     errors: true
     sources:
       .dart_tool/package_config.json: |
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 865813b..5d39cc6 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -9,6 +9,7 @@
 general/error_recovery/issue_39202.crash: SemiFuzzCrash
 general/error_recovery/issue_39058.crash: SemiFuzzFailure
 regress/utf_16_le_content.crash: SemiFuzzCrash
+dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
 
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
diff --git a/tools/VERSION b/tools/VERSION
index 82a934e..efdc31b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 59
+PRERELEASE 60
 PRERELEASE_PATCH 0
\ No newline at end of file