Version 2.13.0-39.0.dev

Merge commit '02f0f53ddf6c91a2bed4614d95743ee56cff8077' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart
new file mode 100644
index 0000000..a3c4ea0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart
@@ -0,0 +1,46 @@
+// 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.
+
+/*library: nnbd=true*/
+
+typedef Typedef1 = void Function();
+typedef Typedef2 = dynamic Function();
+
+/*class: A:A,Object*/
+abstract class A {
+  /*member: A.method1:void Function(void Function())*/
+  void method1(void Function() f);
+
+  /*member: A.method2:void Function(void Function())*/
+  void method2(Typedef1 f);
+
+  /*member: A.method3:void Function(void Function())*/
+  void method3(Typedef1 f);
+
+  /*member: A.method4:void Function(void Function())*/
+  void method4(void Function() f);
+}
+
+/*class: B:B,Object*/
+abstract class B {
+  /*member: B.method1:void Function(dynamic Function())*/
+  void method1(dynamic Function() f);
+
+  /*member: B.method2:void Function(dynamic Function())*/
+  void method2(Typedef2 f);
+
+  /*member: B.method3:void Function(dynamic Function())*/
+  void method3(dynamic Function() f);
+
+  /*member: B.method4:void Function(dynamic Function())*/
+  void method4(Typedef2 f);
+}
+
+/*class: C:A,B,C,Object*/
+abstract class C implements A, B {
+  /*member: C.method1:void Function(Object? Function())*/
+  /*member: C.method2:void Function(Object? Function())*/
+  /*member: C.method3:void Function(Object? Function())*/
+  /*member: C.method4:void Function(Object? Function())*/
+}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 7beabe0..f6a2f41 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -6,6 +6,8 @@
 
 library fasta.incremental_compiler;
 
+import 'dart:async' show Completer;
+
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show ScannerConfiguration;
 
@@ -167,6 +169,10 @@
   IncrementalKernelTarget userCode;
   Set<Library> previousSourceBuilders;
 
+  /// Guard against multiple computeDelta calls at the same time (possibly
+  /// caused by lacking awaits etc).
+  Completer currentlyCompiling;
+
   IncrementalCompiler.fromComponent(
       this.context, this.componentToInitializeFrom,
       [bool outlineOnly, this.incrementalSerializer])
@@ -216,6 +222,10 @@
   @override
   Future<Component> computeDelta(
       {List<Uri> entryPoints, bool fullComponent: false}) async {
+    while (currentlyCompiling != null) {
+      await currentlyCompiling.future;
+    }
+    currentlyCompiling = new Completer();
     if (resetTicker) {
       ticker.reset();
     }
@@ -365,10 +375,17 @@
       NonNullableByDefaultCompiledMode compiledMode = componentWithDill == null
           ? data.component?.mode
           : componentWithDill.mode;
-      return context.options.target.configureComponent(
+      Component result = context.options.target.configureComponent(
           new Component(libraries: outputLibraries, uriToSource: uriToSource))
         ..setMainMethodAndMode(mainMethod?.reference, true, compiledMode)
         ..problemsAsJson = problemsAsJson;
+
+      // We're now done. Allow any waiting compile to start.
+      Completer currentlyCompilingLocal = currentlyCompiling;
+      currentlyCompiling = null;
+      currentlyCompilingLocal.complete();
+
+      return result;
     });
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
index 2f22878..641352a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
@@ -332,6 +332,10 @@
                   _coreTypes,
                   _combinedMemberSignatureType,
                   norm(_coreTypes, getMemberType(index)));
+              assert(
+                  _combinedMemberSignatureType != null,
+                  "No combined member signature found for "
+                  "${_mutualSubtypes.values.map((int i) => getMemberType(i))}");
             }
           }
           _neededNnbdTopMerge =
diff --git a/pkg/front_end/test/multiple_simultaneous_compiles_test.dart b/pkg/front_end/test/multiple_simultaneous_compiles_test.dart
new file mode 100644
index 0000000..6d3e9e1
--- /dev/null
+++ b/pkg/front_end/test/multiple_simultaneous_compiles_test.dart
@@ -0,0 +1,71 @@
+// 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.
+
+// @dart = 2.9
+
+import 'dart:io';
+
+import 'package:front_end/src/api_unstable/vm.dart';
+import 'package:front_end/src/fasta/incremental_compiler.dart';
+import 'package:kernel/ast.dart';
+
+import 'incremental_load_from_dill_suite.dart' show getOptions;
+
+main() async {
+  Uri compileTarget = Platform.script.resolve("binary_md_dill_reader.dart");
+  if (!(new File.fromUri(compileTarget)).existsSync()) {
+    throw "$compileTarget doesn't exist";
+  }
+
+  List<Future> futures = [];
+  List<int> compilesLeft = new List<int>.filled(5, 8);
+  for (int i = 0; i < compilesLeft.length; i++) {
+    Future<Component> compileAgain() async {
+      print("$i has ${compilesLeft[i]} left.");
+      if (compilesLeft[i] > 0) {
+        compilesLeft[i]--;
+        return compile(i, compileTarget).then((value) => compileAgain());
+      }
+      return null;
+    }
+
+    print("Starting first compile for $i");
+    futures.add(compile(i, compileTarget).then((value) => compileAgain()));
+  }
+  await Future.wait(futures);
+
+  print("Checkpoint #1: Can compiles several at once "
+      "(with different compilers!)");
+
+  for (int i = 0; i < 5; i++) {
+    futures.clear();
+    for (int j = 0; j < 10; j++) {
+      futures.add(compile(0, compileTarget));
+    }
+    await Future.wait(futures);
+  }
+
+  print("Checkpoint #2: Can compiles several at once "
+      "(with the same compiler) (without crashing)");
+}
+
+List<IncrementalCompiler> compilers = [];
+
+Future<Component> compile(int compilerNum, Uri uri) async {
+  if (compilers.length <= compilerNum) {
+    compilers.length = compilerNum + 1;
+  }
+  IncrementalCompiler compiler = compilers[compilerNum];
+  if (compiler == null) {
+    var options = getOptions();
+    compiler = new IncrementalCompiler(new CompilerContext(
+        new ProcessedOptions(options: options, inputs: [uri])));
+    compilers[compilerNum] = compiler;
+  } else {
+    compiler.invalidateAllSources();
+  }
+  Component result = await compiler.computeDelta();
+  print("Now compile is done!");
+  return result;
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5d9da02..69f280f 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -75,6 +75,7 @@
 auxiliary
 awaited
 awaiting
+awaits
 b
 b0i
 b0m
@@ -1334,6 +1335,7 @@
 vs
 vtab
 w
+waiting
 waste
 wasted
 watch
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index cd57d77..fa63366 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -162,8 +162,9 @@
   ///
   /// Has no effect if [child] is not actually a child of this node.
   ///
-  /// If [replacement] is `null`, this will [remove] the [child] node.
+  /// [replacement] must be non-null.
   void replaceChild(TreeNode child, TreeNode replacement) {
+    assert(replacement != null);
     transformChildren(new _ChildReplacer(child, replacement));
   }
 
@@ -173,21 +174,13 @@
   /// particular, [replacement] should be an orphan or be part of an orphaned
   /// subtree.
   ///
-  /// If [replacement] is `null`, this will [remove] the node.
+  /// [replacement] must be non-null.
   void replaceWith(TreeNode replacement) {
+    assert(replacement != null);
     parent.replaceChild(this, replacement);
     parent = null;
   }
 
-  /// Removes this node from the [List] it is currently stored in, or assigns
-  /// `null` to the field on the parent currently pointing to the node.
-  ///
-  /// Has no effect if the node is orphaned or if the parent pointer is stale.
-  void remove() {
-    parent?.replaceChild(this, null);
-    parent = null;
-  }
-
   Component get enclosingComponent => parent?.enclosingComponent;
 
   /// Returns the best known source location of the given AST node, or `null` if
@@ -11559,3 +11552,7 @@
 /// `List.filled` constructor.
 const NamedType namedTypeDummy =
     const NamedType('', dartTypeDummy, isRequired: false);
+
+/// Non-nullable `Member` value to be used as a dummy initial value for the
+/// `List.filled` constructor.
+final Member dummyMember = new Field.mutable(new _PublicName(''));
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 30fc980..08ed371 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -248,7 +248,9 @@
       List<Member> first, List<Member> second) {
     if (first.isEmpty) return second;
     if (second.isEmpty) return first;
-    List<Member> result = <Member>[]..length = first.length + second.length;
+    List<Member> result = new List<Member>.filled(
+        first.length + second.length, dummyMember,
+        growable: true);
     int storeIndex = 0;
     int i = 0, j = 0;
     while (i < first.length && j < second.length) {
@@ -1282,8 +1284,9 @@
   static List<Member> _inheritMembers(
       List<Member> declared, List<Member> inherited,
       {bool skipAbstractMembers: false}) {
-    List<Member> result = <Member>[]..length =
-        declared.length + inherited.length;
+    List<Member> result = new List<Member>.filled(
+        declared.length + inherited.length, dummyMember,
+        growable: true);
     // Since both lists are sorted, we can fuse them like in merge sort.
     int storeIndex = 0;
     int i = 0, j = 0;
@@ -1333,7 +1336,8 @@
   /// The input lists must be sorted, and the returned list is sorted.
   static List<Member> _getUnshadowedInheritedMembers(
       List<Member> declared, List<Member> inherited) {
-    List<Member> result = <Member>[]..length = inherited.length;
+    List<Member> result =
+        new List<Member>.filled(inherited.length, dummyMember, growable: true);
     int storeIndex = 0;
     int i = 0, j = 0;
     while (i < declared.length && j < inherited.length) {
@@ -1433,10 +1437,8 @@
     for (Class class_ in _infoMap.keys) {
       _ClassInfo info = _infoMap[class_]!;
       int intervals = info.supertypeIntervalList.length ~/ 2;
-      if (intervals >= result.length) {
-        int oldLength = result.length;
-        result.length = intervals + 1;
-        result.fillRange(oldLength, result.length, 0);
+      while (result.length <= intervals) {
+        result.add(0);
       }
       result[intervals] += 1;
     }
diff --git a/pkg/kernel/lib/src/merge_visitor.dart b/pkg/kernel/lib/src/merge_visitor.dart
index de66d20..f089d75 100644
--- a/pkg/kernel/lib/src/merge_visitor.dart
+++ b/pkg/kernel/lib/src/merge_visitor.dart
@@ -115,9 +115,10 @@
       newNamedParameters[i] = newNamedType;
     }
     TypedefType? newTypedefType;
-    if (a.typedefType != null) {
+    if (a.typedefType != null && b.typedefType != null) {
       newTypedefType = mergeTypes(a.typedefType, b.typedefType) as TypedefType?;
-      if (newTypedefType == null) return null;
+      // If the typedef couldn't be merged we just omit it from the resulting
+      // function type since the typedef type is only informational.
     }
 
     return new FunctionType(newPositionalParameters, newReturnType, nullability,
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index a558085..7e0dc6a 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -350,7 +350,8 @@
         experimentalFlags: experimentalFlags,
         packageConfig: packageConfig,
         invocationModes: invocationModes);
-
+    // TODO(VM TEAM): This does not seem safe. What if cloning while having
+    // pending deltas for instance?
     generator.resetDeltaState();
     Component fullComponent = await generator.compile();
 
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 10cfe47..688af2c 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -348,7 +348,8 @@
     }
     // Remove initializers referring to fields to prevent cascading errors.
     for (final Initializer i in toRemove) {
-      i.remove();
+      final Constructor c = i.parent;
+      c.initializers.remove(i);
     }
 
     // Add a constructor which 'load' can use.
@@ -444,7 +445,7 @@
     }
 
     for (final Field f in fields.values) {
-      f.remove();
+      node.fields.remove(f);
     }
 
     for (final i in getters.keys) {
diff --git a/tools/VERSION b/tools/VERSION
index 9f1a7ac..9c16a52 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 38
+PRERELEASE 39
 PRERELEASE_PATCH 0
\ No newline at end of file