Version 2.19.0-28.0.dev

Merge commit 'a13ef8a5d5e96e1176488c66797181377389bbc3' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index d64e8b8..9a47861 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 41.0.0
+version: 42.0.0
 description: Logic that is shared between the front_end and analyzer packages.
 repository: https://github.com/dart-lang/sdk/tree/main/pkg/_fe_analyzer_shared
 
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index c0781e9..ba6892e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,7 +1,7 @@
-## 4.3.0-dev
+## 4.3.0
 * Deprecated `Directive.keyword`, use corresponding `xyzToken` in specific directives.
 * Deprecated `LibraryElement.parts`, use `parts2` instead.
-* Deprecated `LibraryElement.exports`, use `libraryexports` instead.
+* Deprecated `LibraryElement.exports`, use `libraryExports` instead.
 * Deprecated `LibraryElement.imports`, use `libraryImports` instead.
 * Deprecated `Element.enclosingElement`, use `enclosingElement2` instead.
 * `Member` is not equal to `ElementImpl`, use `Element.declaration`.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 4b27f79..6c3c45f 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 4.3.0-dev
+version: 4.3.0
 description: This package provides a library that performs static analysis of Dart code.
 repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
 
@@ -7,7 +7,7 @@
   sdk: '>=2.17.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^41.0.0
+  _fe_analyzer_shared: ^42.0.0
   collection: ^1.15.0
   convert: ^3.0.0
   crypto: ^3.0.0
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index 2ef3f29..d6e4d47 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -2,8 +2,6 @@
 // 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.10
-
 import '../../common/elements.dart' show CommonElements;
 import '../../constants/values.dart';
 import '../../elements/entities.dart';
@@ -11,7 +9,7 @@
 import '../../elements/types.dart';
 import '../../ir/class_relation.dart';
 import '../../universe/selector.dart';
-import '../../world.dart';
+import '../../world_interfaces.dart';
 import '../abstract_value_domain.dart';
 
 /// This class is used to store bits information about class entities.
@@ -172,7 +170,7 @@
 
   // TODO(coam): This currently returns null if we are not sure if it's a primitive.
   // It could be improved because we can also tell when we're certain it's not a primitive.
-  PrimitiveConstantValue getPrimitiveValue(int value) {
+  PrimitiveConstantValue? getPrimitiveValue(int value) {
     if (isDefinitelyTrue(value)) {
       return TrueConstantValue();
     }
@@ -355,7 +353,7 @@
   }
 
   ClassInfo _computeClassInfo(ClassEntity cls) {
-    ClassInfo classInfo = _storedClassInfo[cls];
+    ClassInfo? classInfo = _storedClassInfo[cls];
     if (classInfo != null) {
       return classInfo;
     }
@@ -442,7 +440,10 @@
   }
 
   int createFromStaticType(DartType type,
-      {ClassRelation classRelation = ClassRelation.subtype, bool nullable}) {
+      {ClassRelation classRelation = ClassRelation.subtype,
+      required bool nullable}) {
+    // TODO(48820): Remove after sound null safety is enabled.
+    // ignore: unnecessary_null_comparison
     assert(nullable != null);
 
     if ((classRelation == ClassRelation.subtype ||
@@ -481,8 +482,6 @@
 
   int _createFromStaticType(
       DartType type, ClassRelation classRelation, bool nullable) {
-    assert(nullable != null);
-
     int finish(int value, bool isPrecise) {
       // [isPrecise] is ignored since we only treat singleton partitions as
       // precise.
@@ -576,26 +575,21 @@
 
   int get emptyType => powersetBottom;
 
-  int _constMapType;
-  int get constMapType => _constMapType ??=
+  late final int constMapType =
       createNonNullSubtype(commonElements.constMapLiteralClass);
 
   int get constSetType => otherValue;
 
-  int _constListType;
-  int get constListType => _constListType ??=
+  late final int constListType =
       createNonNullExact(commonElements.jsUnmodifiableArrayClass);
 
-  int _fixedListType;
-  int get fixedListType =>
-      _fixedListType ??= createNonNullExact(commonElements.jsFixedArrayClass);
+  late final int fixedListType =
+      createNonNullExact(commonElements.jsFixedArrayClass);
 
-  int _growableListType;
-  int get growableListType => _growableListType ??=
+  late final int growableListType =
       createNonNullExact(commonElements.jsExtendableArrayClass);
 
-  int _mutableArrayType;
-  int get mutableArrayType => _mutableArrayType ??=
+  late final int mutableArrayType =
       createNonNullSubtype(commonElements.jsMutableArrayClass);
 
   int get nullType => nullValue;
@@ -605,33 +599,21 @@
   // TODO(fishythefish): Support tracking late sentinels in the powerset domain.
   int get lateSentinelType => powersetBottom;
 
-  int _mapType;
-  int get mapType =>
-      _mapType ??= createNonNullSubtype(commonElements.mapLiteralClass);
+  late final int mapType = createNonNullSubtype(commonElements.mapLiteralClass);
 
-  int _setType;
-  int get setType =>
-      _setType ??= createNonNullSubtype(commonElements.setLiteralClass);
+  late final int setType = createNonNullSubtype(commonElements.setLiteralClass);
 
-  int _listType;
-  int get listType =>
-      _listType ??= createNonNullExact(commonElements.jsArrayClass);
+  late final int listType = createNonNullExact(commonElements.jsArrayClass);
 
-  int _stringType;
-  int get stringType =>
-      _stringType ??= createNonNullSubtype(commonElements.jsStringClass);
+  late final int stringType =
+      createNonNullSubtype(commonElements.jsStringClass);
 
-  int _numType;
-  int get numType =>
-      _numType ??= createNonNullSubclass(commonElements.jsNumberClass);
+  late final int numType = createNonNullSubclass(commonElements.jsNumberClass);
 
-  int _numNotIntType;
-  int get numNotIntType =>
-      _numNotIntType ??= createNonNullExact(commonElements.jsNumNotIntClass);
+  late final int numNotIntType =
+      createNonNullExact(commonElements.jsNumNotIntClass);
 
-  int _intType;
-  int get intType =>
-      _intType ??= createNonNullSubtype(commonElements.jsIntClass);
+  late final int intType = createNonNullSubtype(commonElements.jsIntClass);
 
   int get positiveIntType => intType;
   int get uint32Type => intType;
@@ -639,9 +621,8 @@
 
   int get boolType => boolValue;
 
-  int _functionType;
-  int get functionType =>
-      _functionType ??= createNonNullSubtype(commonElements.functionClass);
+  late final int functionType =
+      createNonNullSubtype(commonElements.functionClass);
 
   int get typeType => otherValue;
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index b63bba17..886ccfc 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -2,8 +2,6 @@
 // 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.10
-
 library js_backend.backend.codegen_listener;
 
 import 'dart:collection';
@@ -101,7 +99,7 @@
 
   @override
   void onQueueOpen(
-      Enqueuer enqueuer, FunctionEntity mainMethod, Iterable<Uri> libraries) {
+      Enqueuer enqueuer, FunctionEntity? mainMethod, Iterable<Uri> libraries) {
     enqueuer.applyImpact(_nativeEnqueuer.processNativeClasses(libraries));
     if (mainMethod != null) {
       enqueuer.applyImpact(_computeMainImpact(mainMethod));
@@ -178,8 +176,8 @@
           .registerTypeUse(TypeUse.instantiation(_commonElements.typeType));
       // If the type is a web component, we need to ensure the constructors are
       // available to 'upgrade' the native object.
-      if (constant.representedType is InterfaceType) {
-        InterfaceType representedType = constant.representedType;
+      final representedType = constant.representedType;
+      if (representedType is InterfaceType) {
         _customElementsAnalysis.registerTypeConstant(representedType.element);
       }
     } else if (constant is InstantiationConstantValue) {
@@ -228,10 +226,10 @@
     _customElementsAnalysis.registerStaticUse(member);
 
     if (member.isFunction && member.isInstanceMember) {
-      ClassEntity cls = member.enclosingClass;
+      ClassEntity cls = member.enclosingClass!;
       if (member.name == Identifiers.call &&
           _elementEnvironment.isGenericClass(cls) &&
-          _rtiNeed.methodNeedsSignature(member)) {
+          _rtiNeed.methodNeedsSignature(member as FunctionEntity)) {
         worldImpact.addImpact(_registerComputeSignature());
       }
     }
diff --git a/pkg/compiler/lib/src/resolution/enqueuer.dart b/pkg/compiler/lib/src/resolution/enqueuer.dart
index 3a27e62..e2af326 100644
--- a/pkg/compiler/lib/src/resolution/enqueuer.dart
+++ b/pkg/compiler/lib/src/resolution/enqueuer.dart
@@ -35,7 +35,7 @@
 
   final Set<ClassEntity> _recentClasses = Setlet<ClassEntity>();
   bool _recentConstants = false;
-  final ResolutionWorldBuilderForEnqueuer worldBuilder;
+  final ResolutionWorldBuilder worldBuilder;
   WorkItemBuilder? _workItemBuilder;
   final DiagnosticReporter _reporter;
   final AnnotationsData _annotationsData;
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 40433ca..a7aa234 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -193,7 +193,7 @@
 }
 
 class ResolutionWorldBuilder extends WorldBuilder
-    implements World, interfaces.ResolutionWorldBuilderForEnqueuer {
+    implements World, interfaces.ResolutionWorldBuilder {
   /// Instantiation information for all classes with instantiated types.
   ///
   /// Invariant: Elements are declaration elements.
@@ -921,6 +921,7 @@
   /// Here `A.m` is inherited into `A`, `B`, and `C`. Because `B` and
   /// `C` implement `I`, `isInheritedInSubtypeOf(A.m, I)` is true, but
   /// `isInheritedInSubtypeOf(A.m, J)` is false.
+  @override
   bool isInheritedIn(
       MemberEntity member, ClassEntity type, ClassRelation relation) {
     // TODO(johnniwinther): Use the [member] itself to avoid enqueueing members
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart b/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
index 6c31592..eae29e5 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
@@ -4,10 +4,12 @@
 
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/class_relation.dart';
 import 'member_usage.dart';
 import 'use.dart';
+import '../world_interfaces.dart';
 
-abstract class ResolutionWorldBuilderForEnqueuer {
+abstract class ResolutionWorldBuilder implements World {
   Iterable<ClassEntity> get directlyInstantiatedClasses;
 
   Iterable<MemberEntity> get processedMembers;
@@ -19,6 +21,9 @@
   void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
       {bool checkEnqueuerConsistency = false});
 
+  bool isInheritedIn(
+      MemberEntity member, ClassEntity type, ClassRelation relation);
+
   void registerDynamicUse(DynamicUse dynamicUse, MemberUsedCallback memberUsed);
 
   bool registerConstantUse(ConstantUse use);
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 7d3e254..1c5c834 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -2,8 +2,6 @@
 // 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.10
-
 library world_builder;
 
 import '../common/elements.dart';
@@ -12,10 +10,10 @@
 import '../elements/types.dart';
 import '../ir/class_relation.dart';
 import '../js_backend/native_data.dart' show NativeBasicData;
-import '../universe/resolution_world_builder.dart' show ResolutionWorldBuilder;
-import '../world.dart' show World;
+import '../world_interfaces.dart' show World;
 import 'selector.dart' show Selector;
 import 'use.dart' show DynamicUse, StaticUse;
+import 'resolution_world_builder_interfaces.dart' show ResolutionWorldBuilder;
 import 'strong_mode_constraint.dart' show StrongModeConstraintInterface;
 
 /// The combined constraints on receivers all the dynamic call sites of the same
@@ -73,7 +71,7 @@
 abstract class UniverseSelectorConstraints extends SelectorConstraints {
   /// Adds [constraint] to these selector constraints. Return `true` if the set
   /// of potential receivers expanded due to the new constraint.
-  bool addReceiverConstraint(covariant Object constraint);
+  bool addReceiverConstraint(covariant Object? constraint);
 }
 
 /// Strategy for computing the constraints on potential receivers of dynamic
@@ -82,7 +80,7 @@
   /// Create a [UniverseSelectorConstraints] to represent the global receiver
   /// constraints for dynamic call sites with [selector].
   UniverseSelectorConstraints createSelectorConstraints(
-      Selector selector, Object initialConstraint);
+      Selector selector, Object? initialConstraint);
 
   /// Returns `true`  if [member] is a potential target of [dynamicUse].
   bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member, World world);
@@ -97,16 +95,16 @@
 
   @override
   StrongModeWorldConstraints createSelectorConstraints(
-      Selector selector, Object initialConstraint) {
+      Selector selector, Object? initialConstraint) {
     return StrongModeWorldConstraints()
-      ..addReceiverConstraint(initialConstraint);
+      ..addReceiverConstraint(initialConstraint as StrongModeConstraint?);
   }
 
   @override
   bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member,
       covariant ResolutionWorldBuilder world) {
     Selector selector = dynamicUse.selector;
-    StrongModeConstraint constraint = dynamicUse.receiverConstraint;
+    final constraint = dynamicUse.receiverConstraint as StrongModeConstraint?;
     return selector.appliesUnnamed(member) &&
         (constraint == null ||
             constraint.canHit(member, selector.memberName, world));
@@ -115,55 +113,41 @@
 
 class StrongModeWorldConstraints extends UniverseSelectorConstraints {
   bool isAll = false;
-  Set<StrongModeConstraint> _constraints;
+  late Set<StrongModeConstraint> _constraints = {};
 
   @override
   bool canHit(MemberEntity element, Name name, World world) {
     if (isAll) return true;
-    if (_constraints == null) return false;
-    for (StrongModeConstraint constraint in _constraints) {
-      if (constraint.canHit(element, name, world)) {
-        return true;
-      }
-    }
-    return false;
+    return _constraints.any((constraint) =>
+        constraint.canHit(element, name, world as ResolutionWorldBuilder));
   }
 
   @override
   bool needsNoSuchMethodHandling(Selector selector, World world) {
-    if (isAll) {
-      return true;
-    }
-    if (_constraints != null) {
-      for (StrongModeConstraint constraint in _constraints) {
-        if (constraint.needsNoSuchMethodHandling(selector, world)) {
-          return true;
-        }
-      }
-    }
-    return false;
+    if (isAll) return true;
+    return _constraints.any(
+        (constraint) => constraint.needsNoSuchMethodHandling(selector, world));
   }
 
   @override
-  bool addReceiverConstraint(StrongModeConstraint constraint) {
+  bool addReceiverConstraint(StrongModeConstraint? constraint) {
     if (isAll) return false;
     if (constraint?.cls == null) {
       isAll = true;
-      _constraints = null;
+      _constraints = const {};
       return true;
     }
-    _constraints ??= {};
-    return _constraints.add(constraint);
+    return _constraints.add(constraint!);
   }
 
   @override
   String toString() {
     if (isAll) {
       return '<all>';
-    } else if (_constraints != null) {
-      return '<${_constraints.map((c) => c.cls).join(',')}>';
-    } else {
+    } else if (_constraints.isEmpty) {
       return '<none>';
+    } else {
+      return '<${_constraints.map((c) => c.cls).join(',')}>';
     }
   }
 }
@@ -238,11 +222,9 @@
   }
 
   void registerStaticInvocation(StaticUse staticUse) {
-    if (staticUse.typeArguments == null || staticUse.typeArguments.isEmpty) {
-      return;
-    }
-    _registerStaticTypeArgumentDependency(
-        staticUse.element, staticUse.typeArguments);
+    final typeArguments = staticUse.typeArguments;
+    if (typeArguments == null || typeArguments.isEmpty) return;
+    _registerStaticTypeArgumentDependency(staticUse.element, typeArguments);
   }
 
   void registerDynamicInvocation(
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 3f9581a..9c400e0 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -48,6 +48,7 @@
 
   InterceptorData get interceptorData;
 
+  @override
   JElementEnvironment get elementEnvironment;
 
   @override
@@ -105,6 +106,7 @@
   Iterable<ClassEntity> mixinUsesOf(ClassEntity cls);
 
   /// Returns `true` if [cls] is mixed into a live class.
+  @override
   bool isUsedAsMixin(ClassEntity cls);
 
   /// Returns `true` if any live class that mixes in [cls] implements [type].
diff --git a/pkg/compiler/lib/src/world_interfaces.dart b/pkg/compiler/lib/src/world_interfaces.dart
index 6009784..fadcbce 100644
--- a/pkg/compiler/lib/src/world_interfaces.dart
+++ b/pkg/compiler/lib/src/world_interfaces.dart
@@ -23,10 +23,14 @@
 
   DartTypes get dartTypes;
 
+  ElementEnvironment get elementEnvironment;
+
   NativeData get nativeData;
 
   AnnotationsData get annotationsData;
 
+  bool isUsedAsMixin(ClassEntity cls);
+
   bool includesClosureCall(Selector selector, AbstractValue? receiver);
 
   Iterable<MemberEntity> locateMembers(
diff --git a/pkg/dart2wasm/lib/closures.dart b/pkg/dart2wasm/lib/closures.dart
index 221113c..6eb4bdf 100644
--- a/pkg/dart2wasm/lib/closures.dart
+++ b/pkg/dart2wasm/lib/closures.dart
@@ -233,6 +233,18 @@
   }
 
   @override
+  void visitSuperPropertyGet(SuperPropertyGet node) {
+    _visitThis();
+    super.visitSuperPropertyGet(node);
+  }
+
+  @override
+  void visitSuperPropertySet(SuperPropertySet node) {
+    _visitThis();
+    super.visitSuperPropertySet(node);
+  }
+
+  @override
   void visitTypeParameterType(TypeParameterType node) {
     if (node.parameter.parent == member.enclosingClass) {
       _visitThis();
diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart
index fb2ac5f..d59ad92 100644
--- a/pkg/dart2wasm/lib/code_generator.dart
+++ b/pkg/dart2wasm/lib/code_generator.dart
@@ -492,7 +492,8 @@
       types.makeType(
           this, TypeParameterType(typeParam, Nullability.nonNullable));
     }
-    _visitArguments(node.arguments, node.targetReference, 1);
+    _visitArguments(
+        node.arguments, node.targetReference, 1 + cls.typeParameters.length);
     call(node.targetReference);
   }
 
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index c130f70..8e6c7d9 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -298,6 +298,28 @@
     };
   }
 
+  // Finds the `main` method for a given library which is assumed to contain
+  // `main`, either directly or indirectly.
+  Procedure _findMainMethod(Library entryLibrary) {
+    // First check to see if the library itself contains main.
+    for (final procedure in entryLibrary.procedures) {
+      if (procedure.name.text == 'main') {
+        return procedure;
+      }
+    }
+
+    // In some cases, a main method is defined in another file, and then
+    // exported. In these cases, we search for the main method in
+    // [additionalExports].
+    for (final export in entryLibrary.additionalExports) {
+      if (export.node is Procedure && export.asProcedure.name.text == 'main') {
+        return export.asProcedure;
+      }
+    }
+    throw ArgumentError(
+        'Entry uri ${entryLibrary.fileUri} has no main method.');
+  }
+
   Uint8List translate() {
     m = w.Module(watchPoints: options.watchPoints);
     voidMarker = w.RefType.def(w.StructType("void"), nullable: true);
@@ -305,8 +327,7 @@
     classInfoCollector.collect();
 
     functions.collectImportsAndExports();
-    mainFunction =
-        libraries.first.procedures.firstWhere((p) => p.name.text == "main");
+    mainFunction = _findMainMethod(libraries.first);
     functions.addExport(mainFunction.reference, "main");
 
     initFunction = m.addFunction(functionType(const [], const []), "#init");
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 6a2f7b6..a976f9e4 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -260,81 +260,99 @@
 ///
 /// NOTE: The contents of [args] may be modified before calling [f]. If it
 /// originated outside of the SDK it must be copied first.
-_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
-    JS('', '''(() => {
-  $trackCall($obj);
+_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) {
+  trackCall(obj);
+  var originalTarget = JS<bool>('!', '# === void 0', obj) ? f : obj;
 
-  let originalTarget = obj === void 0 ? f : obj;
-
-  function callNSM(errorMessage) {
-    return $noSuchMethod(originalTarget, new $InvocationImpl.new(
-        $displayName, $args, {
-          namedArguments: $named,
-          // Repeated the default value here to avoid passing null from JS to a
-          // non-nullable argument.
-          typeArguments: $typeArgs || [],
-          isMethod: true,
-          failureMessage: errorMessage
-        }));
+  callNSM(@notNull String errorMessage) {
+    return noSuchMethod(
+        originalTarget,
+        InvocationImpl(displayName, JS<List<Object?>>('!', '#', args),
+            namedArguments: named,
+            // Repeated the default value here in JS to preserve the historic
+            // behavior.
+            typeArguments: JS('!', '# || []', typeArgs),
+            isMethod: true,
+            failureMessage: errorMessage));
   }
-  if ($f == null) return callNSM('Dynamic call of null.');
-  if (!($f instanceof Function)) {
+
+  if (f == null) return callNSM('Dynamic call of null.');
+  if (!JS<bool>('!', '# instanceof Function', f)) {
     // We're not a function (and hence not a method either)
     // Grab the `call` method if it's not a function.
-    if ($f != null) {
+    if (f != null) {
       // Getting the member succeeded, so update the originalTarget.
       // (we're now trying `call()` on `f`, so we want to call its nSM rather
       // than the original target's nSM).
       originalTarget = f;
-      $f = ${bindCall(f, _canonicalMember(f, 'call'))};
-      $ftype = null;
-      $displayName = "call";
+      f = bindCall(f, _canonicalMember(f, 'call'));
+      ftype = null;
+      displayName = 'call';
     }
-    if ($f == null) return callNSM(
-        "Dynamic call of object has no instance method 'call'.");
+    if (f == null) {
+      return callNSM("Dynamic call of object has no instance method 'call'.");
+    }
   }
   // If f is a function, but not a method (no method type)
   // then it should have been a function valued field, so
   // get the type from the function.
-  if ($ftype == null) $ftype = $f[$_runtimeType];
+  if (ftype == null) ftype = JS('', '#[#]', f, _runtimeType);
 
-  if ($ftype == null) {
+  if (ftype == null) {
     // TODO(leafp): Allow JS objects to go through?
-    if ($typeArgs != null) {
+    if (typeArgs != null) {
       // TODO(jmesserly): is there a sensible way to handle these?
-      $throwTypeError('call to JS object `' + $obj +
-          '` with type arguments <' + $typeArgs + '> is not supported.');
+      throwTypeError('call to JS object `' +
+          // Not a String but historically relying on the default JavaScript
+          // behavior.
+          JS<String>('!', '#', obj) +
+          '` with type arguments <' +
+          // Not a String but historically relying on the default JavaScript
+          // behavior.
+          JS<String>('!', '#', typeArgs) +
+          '> is not supported.');
     }
 
-    if ($named != null) $args.push($named);
-    return $f.apply($obj, $args);
+    if (named != null) JS('', '#.push(#)', args, named);
+    return JS('', '#.apply(#, #)', f, obj, args);
   }
 
   // Apply type arguments
-  if (${_jsInstanceOf(ftype, GenericFunctionType)}) {
-    let formalCount = $ftype.formalCount;
+  if (_jsInstanceOf(ftype, GenericFunctionType)) {
+    var formalCount = JS<int>('!', '#.formalCount', ftype);
 
-    if ($typeArgs == null) {
-      $typeArgs = $ftype.instantiateDefaultBounds();
-    } else if ($typeArgs.length != formalCount) {
+    if (typeArgs == null) {
+      typeArgs = JS<List>('!', '#.instantiateDefaultBounds()', ftype);
+    } else if (JS<bool>('!', '#.length != #', typeArgs, formalCount)) {
       return callNSM('Dynamic call with incorrect number of type arguments. ' +
-          'Expected: ' + formalCount + ' Actual: ' + $typeArgs.length);
+          'Expected: ' +
+          // Not a String but historically relying on the default JavaScript
+          // behavior.
+          JS<String>('!', '#', formalCount) +
+          ' Actual: ' +
+          // Not a String but historically relying on the default JavaScript
+          // behavior.
+          JS<String>('!', '#.length', typeArgs));
     } else {
-      $ftype.checkBounds($typeArgs);
+      JS('', '#.checkBounds(#)', ftype, typeArgs);
     }
-    $ftype = $ftype.instantiate($typeArgs);
-  } else if ($typeArgs != null) {
+    ftype = JS('', '#.instantiate(#)', ftype, typeArgs);
+  } else if (typeArgs != null) {
     return callNSM('Dynamic call with unexpected type arguments. ' +
-        'Expected: 0 Actual: ' + $typeArgs.length);
+        'Expected: 0 Actual: ' +
+        // Not a String but historically relying on the default JavaScript
+        // behavior.
+        JS<String>('!', '#.length', typeArgs));
   }
-  let errorMessage = $_argumentErrors($ftype, $args, $named);
+  var errorMessage = _argumentErrors(
+      JS<FunctionType>('!', '#', ftype), JS<List>('!', '#', args), named);
   if (errorMessage == null) {
-    if ($typeArgs != null) $args = $typeArgs.concat($args);
-    if ($named != null) $args.push($named);
-    return $f.apply($obj, $args);
+    if (typeArgs != null) args = JS('', '#.concat(#)', typeArgs, args);
+    if (named != null) JS('', '#.push(#)', args, named);
+    return JS('', '#.apply(#, #)', f, obj, args);
   }
   return callNSM(errorMessage);
-})()''');
+}
 
 dcall(f, args, [@undefined named]) => _checkAndCall(
     f, null, JS('', 'void 0'), null, args, named, JS('', 'f.name'));
diff --git a/tools/VERSION b/tools/VERSION
index 83893d8..7f5c1e2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 27
+PRERELEASE 28
 PRERELEASE_PATCH 0
\ No newline at end of file