// Copyright (c) 2017, 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.

import 'dart:collection';
import 'dart:convert';
import 'dart:io' as io;
import 'dart:math' show max, min;

import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
    show ExtensionIndex;
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:js_shared/synced/embedded_names.dart' show JsGetName, JsBuiltin;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/library_index.dart';
import 'package:kernel/src/dart_type_equivalence.dart';
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart' show SourceLocation;

import '../command/options.dart' show Options;
import '../compiler/js_names.dart' as js_ast;
import '../compiler/js_utils.dart' as js_ast;
import '../compiler/module_builder.dart'
    show isSdkInternalRuntimeUri, libraryUriToJsIdentifier;
import '../compiler/module_containers.dart' show ModuleItemContainer;
import '../compiler/rewrite_async.dart';
import '../js_ast/js_ast.dart' as js_ast;
import '../js_ast/js_ast.dart' show ModuleItem, js;
import '../js_ast/source_map_printer.dart'
    show NodeEnd, NodeSpan, HoverComment, continueSourceMap;
import 'constants.dart';
import 'future_or_normalizer.dart';
import 'js_interop.dart';
import 'js_typerep.dart';
import 'kernel_helpers.dart';
import 'native_types.dart';
import 'nullable_inference.dart';
import 'property_model.dart';
import 'target.dart' show allowedNativeTest;
import 'type_environment.dart';
import 'type_recipe_generator.dart';
import 'type_table.dart';

/// Public API for DDC compilers.
abstract class Compiler {
  js_ast.Program emitModule(Component component);
  Map<Class, js_ast.Identifier> get classIdentifiers;
  Map<Member, String> get memberNames;
  Map<Procedure, js_ast.Identifier> get procedureIdentifiers;
  Map<VariableDeclaration, js_ast.Identifier> get variableIdentifiers;
  js_ast.Fun emitFunctionIncremental(List<ModuleItem> items, Library library,
      Class? cls, FunctionNode functionNode, String name);
}

class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
    with OnceConstantVisitorDefaultMixin<js_ast.Expression>
    implements
        StatementVisitor<js_ast.Statement>,
        ExpressionVisitor<js_ast.Expression>,
        Compiler {
  final Options _options;

  /// Maps each `Class` node compiled in the module to the `Identifier`s used to
  /// name the class in JavaScript.
  ///
  /// This mapping is used when generating the symbol information for the
  /// module.
  @override
  final classIdentifiers = <Class, js_ast.Identifier>{};

  /// Maps each class `Member` node compiled in the module to the name used for
  /// the member in JavaScript.
  ///
  /// This mapping is used when generating the symbol information for the
  /// module.
  @override
  final memberNames = <Member, String>{};

  /// Maps each `Procedure` node compiled in the module to the `Identifier`s
  /// used to name the class in JavaScript.
  ///
  /// This mapping is used when generating the symbol information for the
  /// module.
  @override
  final procedureIdentifiers = <Procedure, js_ast.Identifier>{};

  /// Maps each `VariableDeclaration` node compiled in the module to the name
  /// used for the variable in JavaScript.
  ///
  /// This mapping is used when generating the symbol information for the
  /// module.
  @override
  final variableIdentifiers = <VariableDeclaration, js_ast.Identifier>{};

  /// Identifiers for kernel variables with an analgous identifier in JS.
  ///
  /// [VariableDeclaration.name] is not necessarily a safe identifier for JS
  /// transpiled code. The same name can be used in shadowing contexts. We map
  /// each kernel variable to a [js_ast.ScopedId] so that at code emission
  /// time, declarations that would be shadowed are given a unique name. If
  /// there is no risk of shadowing, the original name will be used.
  final Map<VariableDeclaration, js_ast.ScopedId> _variableTempIds = {};

  /// Maps a library URI import, that is not in [_libraries], to the
  /// corresponding Kernel summary module we imported it with.
  ///
  /// An entry must exist for every reachable component.
  final Map<Library, Component> _importToSummary;

  /// Maps a Kernel summary to the JS import name for the module.
  ///
  /// An entry must exist for every reachable component.
  final Map<Component, String> _summaryToModule;

  /// The variable for the current catch clause
  VariableDeclaration? _rethrowParameter;

  Set<Class>? _pendingClasses;

  /// Temporary variables mapped to their corresponding JavaScript variable.
  final _tempVariables = <VariableDeclaration, js_ast.ScopedId>{};

  /// Let variables collected for the given function.
  List<js_ast.ScopedId>? _letVariables;

  final _constTable = js_ast.Identifier('CT');

  /// Constant getters used to populate the constant table.
  final _constLazyAccessors = <js_ast.Method>[];

  /// Container for holding the results of lazily-evaluated constants.
  var _constTableCache = ModuleItemContainer<String>.asArray('C');

  /// Tracks the index in [_moduleItems] where the const table must be inserted.
  /// Required for SDK builds due to internal circular dependencies.
  /// E.g., dart.constList depends on JSArray.
  int _constTableInsertionIndex = 0;

  /// The class that is emitting its base class or mixin references, otherwise
  /// null.
  ///
  /// This is not used when inside the class method bodies, or for other type
  /// information such as `implements`.
  Class? _classEmittingExtends;

  /// The class that is emitting its signature information, otherwise null.
  Class? _classEmittingSignatures;

  /// True when a class is emitting a deferred class hierarchy.
  bool _emittingDeferredType = false;

  /// The current type environment of type parameters introduced to the scope
  /// via generic classes and functions.
  DDCTypeEnvironment _currentTypeEnvironment = const EmptyTypeEnvironment();

  final TypeRecipeGenerator _typeRecipeGenerator;

  /// Visitor used for testing static invocations in the dart:_rti library to
  /// determine if they are suitable for inlining at call sites.
  final BasicInlineTester _inlineTester;

  /// The current element being loaded.
  /// We can use this to determine if we're loading top-level code or not:
  ///
  ///     _currentClass == _classEmittingTopLevel
  ///
  Class? _currentClass;

  /// The current source file URI for emitting in the source map.
  Uri? _currentUri;

  late Component _component;

  /// The current library being compiled.
  Library? _currentLibrary;

  /// The current function being compiled, if any.
  FunctionNode? _currentFunction;

  /// Whether the current function needs to insert parameter checks.
  ///
  /// Used to avoid adding checks for formal parameters inside a synthetic
  /// function that is generated during expression compilation in the
  /// incremental compiler, since those checks would already be done in
  /// the original code.
  bool _checkParameters = true;

  /// Whether we are currently generating code for the body of a `JS()` call.
  bool _isInForeignJS = false;

  /// Table of named and possibly hoisted types.
  late TypeTable _typeTable;

  /// The global extension type table.
  // TODO(jmesserly): rename to `_nativeTypes`
  final NativeTypeSet _extensionTypes;

  final CoreTypes _coreTypes;

  final TypeEnvironment _types;

  final StatefulStaticTypeContext _staticTypeContext;

  final ClassHierarchy _hierarchy;

  /// Information about virtual and overridden fields/getters/setters in the
  /// class we're currently compiling, or `null` if we aren't compiling a class.
  ClassPropertyModel? _classProperties;

  /// Information about virtual fields for all libraries in the current build
  /// unit.
  final _virtualFields = VirtualFieldModel();

  final JSTypeRep _typeRep;

  bool _superAllowed = true;
  bool _optimizeNonVirtualFieldAccess = true;

  final _superHelpers = <String, js_ast.Method>{};

  /// Cache for the results of calling [_requiresRtiForInstantiation].
  final _requiresRtiForInstantiationCache = <Class, bool>{};

  /// Reserved parameter used to reference RTI objects passed to generic
  /// constructors/factories and generic method signatures.
  final _rtiParam = js_ast.ScopedId('_ti');

  // Compilation of Kernel's [BreakStatement].
  //
  // Kernel represents Dart's `break` and `continue` uniformly as
  // [BreakStatement], by representing a loop continue as a break from the
  // loop's body.  [BreakStatement] always targets an enclosing
  // [LabeledStatement] statement directly without naming it.  (Continue to
  // a labeled switch case is not represented by a [BreakStatement].)
  //
  // We prefer to compile to `continue` where possible and to avoid labeling
  // statements where it is not necessary.  We maintain some state to track
  // which statements can be targets of break or continue without a label, which
  // statements must be labeled to be targets, and the labels that have been
  // assigned.

  /// A list of statements that can be the target of break without a label.
  ///
  /// A [BreakStatement] targeting any [LabeledStatement] in this list can be
  /// compiled to a break without a label.  All the statements in the list have
  /// the same effective target which must compile to something that can be
  /// targeted by break in JS.  This list and [_currentContinueTargets] are
  /// disjoint.
  List<LabeledStatement> _currentBreakTargets = [];

  /// A list of statements that can be the target of a continue without a label.
  ///
  /// A [BreakStatement] targeting any [LabeledStatement] in this list can be
  /// compiled to a continue without a label.  All the statements in this list
  /// have the same effective target which must compile to something that can be
  /// targeted by continue in JS.  This list and [_currentBreakTargets] are
  /// disjoint.
  List<LabeledStatement> _currentContinueTargets = [];

  /// A map from labeled statements to their 'effective targets'.
  ///
  /// The effective target of a labeled loop body is the enclosing loop.  A
  /// [BreakStatement] targeting this statement can be compiled to `continue`
  /// either with or without a label.  The effective target of a labeled
  /// statement that is not a loop body is the outermost non-labeled statement
  /// that it encloses.  A [BreakStatement] targeting this statement can be
  /// compiled to `break` either with or without a label.
  final _effectiveTargets = HashMap<LabeledStatement, Statement>.identity();

  /// A map from effective targets to their label names.
  ///
  /// If the target needs to be labeled when compiled to JS, because it was
  /// targeted by a break or continue with a label, then this map contains the
  /// label name that was assigned to it.
  final _labelNames = HashMap<Statement, String>.identity();

  /// Indicates that the current context exists within a switch statement that
  /// uses at least one continue statement with a target label.
  ///
  /// JS forbids labels at case statement boundaries, so these switch
  /// statements must be generated less directly.
  /// Updated from the method 'visitSwitchStatement'.
  bool _inLabeledContinueSwitch = false;

  /// A map from switch statements to their state information.
  /// State information includes the names of the switch statement's implicit
  /// label name and implicit state variable name.
  ///
  /// Entries are only created for switch statements that contain labeled
  /// continue statements and are used to simulate "jumping" to case statements.
  /// State variables hold the next constant case expression, while labels act
  /// as targets for continue and break.
  final _switchLabelStates = HashMap<Statement, _SwitchLabelState>();

  /// Maps Kernel constants to their JS aliases.
  final _constAliasCache = HashMap<Constant, js_ast.Expression>();

  /// Maps uri strings in asserts and elsewhere to hoisted identifiers.
  var _uriContainer = ModuleItemContainer<String>.asArray('I');

  /// Index of extension and extension type members in order to filter static
  /// interop members.
  // TODO(srujzs): Is there some way to share this from the js_util_optimizer to
  // avoid having to recompute?
  final ExtensionIndex _extensionIndex;

  /// When inside a `[]=` operator, this will be a non-null value that should be
  /// returned by any `return;` statement.
  ///
  /// This lets DDC use the setter method's return value directly.
  final _operatorSetResultStack = <js_ast.Identifier?>[];

  /// Private member names in this module, organized by their library.
  final _privateNames = HashMap<Library, HashMap<String, js_ast.ScopedId>>();

  /// Holds all top-level JS symbols (used for caching or indexing fields).
  final _symbolContainer = ModuleItemContainer<js_ast.Identifier>.asObject('S',
      keyToString: (js_ast.Identifier i) => i.name);

  /// Extension member symbols for adding Dart members to JS types.
  ///
  /// These are added to the [_extensionSymbolsModule]; see that field for more
  /// information.
  final _extensionSymbols = <String, js_ast.ScopedId>{};

  /// The set of libraries we are currently compiling, and the temporaries used
  /// to refer to them.
  final _libraries = <Library, js_ast.Identifier>{};

  /// Imported libraries, and the temporaries used to refer to them.
  final _imports = <Library, js_ast.ScopedId>{};

  /// Incremental mode for expression compilation.
  ///
  /// If set to true, triggers emitting all used types, symbols, libraries,
  /// constants, urs inside the generated function.
  bool _incrementalMode = false;

  /// Modules and libraries accessed during compilation in incremental mode.
  final _incrementalModules = <String, Set<String>>{};

  /// The identifier used to reference DDC's core "dart:_runtime" library from
  /// generated JS code, typically called "dart" e.g. `dart.dcall`.
  late final js_ast.Identifier _runtimeModule;

  /// The identifier used to reference DDC's "extension method" symbols, used to
  /// safely add Dart-specific member names to JavaScript classes, such as
  /// primitive types (e.g. String) or DOM types in "dart:html".
  late final js_ast.Identifier _extensionSymbolsModule;

  /// The identifier used to reference DDC's core "dart:_rti" library from
  /// generated JS code.
  ///
  /// Must manually name the dart:_rti library because there are local variables
  /// within the library that inadvertently shadow the default name.
  final _rtiLibraryId = js_ast.ScopedId('dart_rti');

  /// The library referred to by [_rtiLibraryId].
  final Library _rtiLibrary;

  /// The `Rti` class defined in [_rtiLibrary].
  final Class _rtiClass;

  /// Whether we're currently building the SDK, which may require special
  /// bootstrapping logic.
  ///
  /// This is initialized by [emitModule], which must be called before
  /// accessing this field.
  bool _isBuildingSdk = false;

  /// Whether or not to move top level symbols into top-level containers.
  ///
  /// This is set in both [emitModule] and [_emitLibrary].
  /// Depends on [_isBuildingSdk].
  bool _containerizeSymbols = false;

  /// The temporary variable that stores named arguments (these are passed via a
  /// JS object literal, to match JS conventions).
  final _namedArgumentTemp = js_ast.ScopedId('opts');

  /// The list of output module items, in the order they need to be emitted in.
  final _moduleItems = <js_ast.ModuleItem>[];

  /// Like [_moduleItems] but for items that should be emitted after classes.
  ///
  /// This is used for deferred supertypes of mutually recursive non-generic
  /// classes.
  final _afterClassDefItems = <js_ast.ModuleItem>[];

  /// The entrypoint method of a dynamic module, if any.
  Procedure? _dynamicEntrypoint;

  final Class _jsArrayClass;
  final Class _privateSymbolClass;
  final Class _linkedHashMapImplClass;
  final Class _identityHashMapImplClass;
  final Class _linkedHashSetClass;
  final Class _linkedHashSetImplClass;
  final Class _identityHashSetImplClass;
  // Helpers for async function lowering
  final Member _asyncStartMember;
  final Member _asyncAwaitMember;
  final Member _asyncReturnMember;
  final Member _asyncRethrowMember;
  final Member _asyncMakeCompleterMember;
  final Member _asyncWrapJsFunctionMember;
  // Helpers for sync* function lowering
  final Member _syncStarMakeIterableMember;
  final Member _syncStarIteratorCurrentMember;
  final Member _syncStarIteratorDatumMember;
  final Member _syncStarIteratorYieldStarMember;
  // Helpers for async* function lowering
  final Member _asyncStarHelperMember;
  final Member _asyncStreamOfControllerMember;
  final Member _asyncMakeAsyncStarStreamControllerMember;
  final Member _asyncIterationMarkerYieldSingleMember;
  final Member _asyncIterationMarkerYieldStarMember;
  final Class _asyncStreamIteratorClass;

  final Procedure _assertInteropMethod;

  final DevCompilerConstants _constants;

  final NullableInference _nullableInference;

  bool _moduleEmitted = false;

  /// Supports verbose logging with a timer.
  Ticker? _ticker;

  factory ProgramCompiler(
    Component component,
    ClassHierarchy hierarchy,
    Options options,
    Map<Library, Component> importToSummary,
    Map<Component, String> summaryToModule, {
    CoreTypes? coreTypes,
    Ticker? ticker,
  }) {
    coreTypes ??= CoreTypes(component);
    var types = TypeEnvironment(coreTypes, hierarchy);
    var constants = DevCompilerConstants();
    var nativeTypes = NativeTypeSet(coreTypes, constants, component);
    var jsTypeRep = JSTypeRep(types, hierarchy);
    var staticTypeContext = StatefulStaticTypeContext.stacked(types);
    return ProgramCompiler._(
      ticker,
      coreTypes,
      coreTypes.index,
      nativeTypes,
      constants,
      types,
      hierarchy,
      jsTypeRep,
      NullableInference(jsTypeRep, staticTypeContext, options: options),
      staticTypeContext,
      options,
      importToSummary,
      summaryToModule,
    );
  }

  ProgramCompiler._(
      this._ticker,
      this._coreTypes,
      LibraryIndex sdk,
      this._extensionTypes,
      this._constants,
      this._types,
      this._hierarchy,
      this._typeRep,
      this._nullableInference,
      this._staticTypeContext,
      this._options,
      this._importToSummary,
      this._summaryToModule)
      : _jsArrayClass = sdk.getClass('dart:_interceptors', 'JSArray'),
        _privateSymbolClass = sdk.getClass('dart:_js_helper', 'PrivateSymbol'),
        _linkedHashMapImplClass = sdk.getClass('dart:_js_helper', 'LinkedMap'),
        _identityHashMapImplClass =
            sdk.getClass('dart:_js_helper', 'IdentityMap'),
        _linkedHashSetClass = sdk.getClass('dart:collection', 'LinkedHashSet'),
        _linkedHashSetImplClass = sdk.getClass('dart:_js_helper', 'LinkedSet'),
        _identityHashSetImplClass =
            sdk.getClass('dart:_js_helper', 'IdentitySet'),
        _assertInteropMethod =
            sdk.getTopLevelProcedure('dart:_runtime', 'assertInterop'),
        _asyncStartMember =
            sdk.getTopLevelMember('dart:async', '_asyncStartSync'),
        _asyncAwaitMember = sdk.getTopLevelMember('dart:async', '_asyncAwait'),
        _asyncReturnMember =
            sdk.getTopLevelMember('dart:async', '_asyncReturn'),
        _asyncRethrowMember =
            sdk.getTopLevelMember('dart:async', '_asyncRethrow'),
        _asyncMakeCompleterMember =
            sdk.getTopLevelMember('dart:async', '_makeAsyncAwaitCompleter'),
        _asyncWrapJsFunctionMember =
            sdk.getTopLevelMember('dart:async', '_wrapJsFunctionForAsync'),
        _syncStarMakeIterableMember =
            sdk.getTopLevelMember('dart:async', '_makeSyncStarIterable'),
        _syncStarIteratorCurrentMember =
            sdk.getMember('dart:async', '_SyncStarIterator', '_current'),
        _syncStarIteratorDatumMember =
            sdk.getMember('dart:async', '_SyncStarIterator', '_datum'),
        _syncStarIteratorYieldStarMember =
            sdk.getMember('dart:async', '_SyncStarIterator', '_yieldStar'),
        _asyncStarHelperMember =
            sdk.getTopLevelMember('dart:async', '_asyncStarHelper'),
        _asyncStreamOfControllerMember =
            sdk.getTopLevelMember('dart:async', '_streamOfController'),
        _asyncMakeAsyncStarStreamControllerMember = sdk.getTopLevelMember(
            'dart:async', '_makeAsyncStarStreamController'),
        _asyncIterationMarkerYieldSingleMember =
            sdk.getMember('dart:async', '_IterationMarker', 'yieldSingle'),
        _asyncIterationMarkerYieldStarMember =
            sdk.getMember('dart:async', '_IterationMarker', 'yieldStar'),
        _asyncStreamIteratorClass =
            sdk.getClass('dart:async', 'StreamIterator'),
        _futureOrNormalizer = FutureOrNormalizer(_coreTypes),
        _typeRecipeGenerator = TypeRecipeGenerator(_coreTypes, _hierarchy),
        _extensionIndex =
            ExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment),
        _inlineTester = BasicInlineTester(_constants),
        _rtiLibrary = sdk.getLibrary('dart:_rti'),
        _rtiClass = sdk.getClass('dart:_rti', 'Rti');

  /// The library for dart:core in the SDK.
  Library get _coreLibrary => _coreTypes.coreLibrary;

  /// The type used for private Dart [Symbol]s.
  InterfaceType get _privateSymbolType =>
      _coreTypes.nonNullableRawType(_privateSymbolClass);

  /// The type used for public Dart [Symbol]s.
  InterfaceType get _internalSymbolType =>
      _coreTypes.nonNullableRawType(_coreTypes.internalSymbolClass);

  final FutureOrNormalizer _futureOrNormalizer;

  /// Module can be emitted only once, and the compiler can be reused after
  /// only in incremental mode, for expression compilation only.
  @override
  js_ast.Program emitModule(Component component) {
    assert(!_options.emitLibraryBundle);
    if (_moduleEmitted) {
      throw StateError('Can only call emitModule once.');
    }
    _ticker?.logMs('Emitting module');
    _component = component;

    var libraries = component.libraries;

    // Initialize library variables.
    _isBuildingSdk = libraries.any(_isSdkInternalRuntime);

    // For runtime performance reasons, we only containerize SDK symbols in web
    // libraries. Otherwise, we use a 600-member cutoff before a module is
    // containerized. This is somewhat arbitrary but works promisingly for the
    // SDK and Flutter Web.
    if (!_isBuildingSdk) {
      // The number of DDC top-level symbols scales with the number of
      // non-static class members across an entire module.
      var uniqueNames = HashSet<String>();
      libraries.forEach((Library l) {
        l.classes.forEach((Class c) {
          c.members.forEach((m) {
            var isStatic =
                m is Field ? m.isStatic : (m is Procedure ? m.isStatic : false);
            if (isStatic) return;
            var name = js_ast.toJSIdentifier(
                m.name.text.replaceAll(js_ast.invalidCharInIdentifier, '_'));
            uniqueNames.add(name);
          });
        });
      });
      _containerizeSymbols = uniqueNames.length > 600;
    }

    var items = _startModule(libraries);
    // TODO(nshahan) Move into `startModule()` once `SharedCompiler` and
    // `ProgramCompiler` have been refactored together.
    if (!_isBuildingSdk) {
      _forceLibraryImport(_rtiLibrary, _rtiLibraryId);
    }

    _nullableInference.allowNotNullDeclarations = _isBuildingSdk;
    _typeTable = TypeTable('T', _runtimeCall);

    // Collect all class/type Element -> Node mappings
    // in case we need to forward declare any classes.
    var classes = HashSet<Class>.identity();
    for (var l in libraries) {
      classes.addAll(l.classes);
    }
    _pendingClasses = classes;

    // Insert a circular reference so neither the constant table or its cache
    // are optimized away by V8. Required for expression evaluation.
    var constTableDeclaration =
        js.statement('const # = Object.create({# : () => (#, #)});', [
      _constTable,
      js_ast.LiteralString('_'),
      _constTableCache.containerId,
      _constTable
    ]);
    _moduleItems.add(constTableDeclaration);

    // Record a safe index after the declaration of type generators and
    // top-level symbols but before the declaration of any functions.
    // Various preliminary data structures must be inserted here prior before
    // referenced by the rest of the module.
    var safeDeclarationIndex = _moduleItems.length;
    _constTableInsertionIndex = safeDeclarationIndex;

    // Add implicit dart:core dependency so it is first.
    _emitLibraryName(_coreTypes.coreLibrary);
    _ticker?.logMs('Added table declarations');

    // Visit each library and emit its code.
    //
    // NOTE: classes are not necessarily emitted in this order.
    // Order will be changed as needed so the resulting code can execute.
    // This is done by forward declaring items.
    libraries.forEach(_emitLibrary);
    _ticker?.logMs('Emitted ${libraries.length} libraries');

    // Emit hoisted assert strings
    _moduleItems.insertAll(safeDeclarationIndex, _uriContainer.emit());

    _moduleItems.insertAll(safeDeclarationIndex, _constTableCache.emit());

    if (_constLazyAccessors.isNotEmpty) {
      var constTableBody = _runtimeStatement(
          'defineLazy(#, { # })', [_constTable, _constLazyAccessors]);
      _moduleItems.insert(_constTableInsertionIndex, constTableBody);
      _constLazyAccessors.clear();
    }

    _moduleItems.addAll(_afterClassDefItems);
    _afterClassDefItems.clear();
    // Register the local const cache for this module so it can be cleared on a
    // hot restart.
    if (_constTableCache.isNotEmpty) {
      _moduleItems.add(_runtimeCall('moduleConstCaches.set(#, #)', [
        js_ast.string(_options.moduleName),
        _constTableCache.containerId
      ]).toStatement());
    }
    _ticker?.logMs('Added table caches');
    // Add all type hierarchy rules for the interface types used in this module.
    // TODO(nshahan) This is likely more information than the application
    // really uses. It could be reduced to only the types of values that are
    // potentially "live" in the module which includes the types of all the
    // constructor invocations and the types of the constructors torn off
    // (potentially constructed) within the module. The current constructor
    // tearoff lowering does make this harder to know since all constructors
    // appeared to be invoked in the body of the method created by the
    // lowering. For now we over estimate and simply use all the interface
    // types introduced by all the classes defined in the module.
    for (var library in libraries) {
      for (var cls in library.classes) {
        var type = cls.getThisType(_coreTypes, Nullability.nonNullable);
        _typeRecipeGenerator.addLiveTypeAncestries(type);
      }
    }
    var universeClass =
        _rtiLibrary.classes.firstWhere((cls) => cls.name == '_Universe');
    var typeRules = _typeRecipeGenerator.liveInterfaceTypeRules;
    var legacyJavaScriptObjectRecipe = _typeRecipeGenerator.interfaceTypeRecipe(
        _coreTypes.index
            .getClass('dart:_interceptors', 'LegacyJavaScriptObject'));
    var legacyJavaScriptObjectRules =
        typeRules.remove(legacyJavaScriptObjectRecipe);
    if (typeRules.isNotEmpty) {
      var template = '#._Universe.#(#, JSON.parse(#))';
      var addRulesStatement = js.call(template, [
        _emitLibraryName(_rtiLibrary),
        _emitMemberName('addRules', memberClass: universeClass),
        _runtimeCall('typeUniverse'),
        js.string(jsonEncode(typeRules), "'")
      ]).toStatement();
      _moduleItems.add(addRulesStatement);
    }
    if (legacyJavaScriptObjectRules != null) {
      var legacyJavaScriptObjectAddRules = {
        legacyJavaScriptObjectRecipe: legacyJavaScriptObjectRules
      };
      // The recipe for 'LegacyJavaScriptObject' is updated during the lifetime
      // of the program and should be emitted with 'addOrUpdateRules' to avoid
      // clobbering its previous state.
      var updateRulesStatement =
          js.statement('#._Universe.#(#, JSON.parse(#))', [
        _emitLibraryName(_rtiLibrary),
        _emitMemberName('addOrUpdateRules', memberClass: universeClass),
        _runtimeCall('typeUniverse'),
        js.string(jsonEncode(legacyJavaScriptObjectAddRules), "'")
      ]);
      _moduleItems.add(updateRulesStatement);
    }
    // Update type rules for `LegacyJavaScriptObject` to add all interop
    // types in this module as a supertype.
    var updateRules = _typeRecipeGenerator.updateLegacyJavaScriptObjectRules;
    if (updateRules.isNotEmpty) {
      // All JavaScript interop classes should be mutual subtypes with
      // `LegacyJavaScriptObject`. To achieve this the rules are manually
      // added here. There is special redirecting rule logic in the dart:_rti
      // library for interop types because otherwise they would duplicate
      // a lot of supertype information.
      var updateRulesStatement =
          js.statement('#._Universe.#(#, JSON.parse(#))', [
        _emitLibraryName(_rtiLibrary),
        _emitMemberName('addOrUpdateRules', memberClass: universeClass),
        _runtimeCall('typeUniverse'),
        js.string(jsonEncode(updateRules), "'")
      ]);
      _moduleItems.add(updateRulesStatement);
    }
    var jsInteropTypeRecipes = _typeRecipeGenerator.visitedJsInteropTypeRecipes;
    if (jsInteropTypeRecipes.isNotEmpty) {
      // Update the `LegacyJavaScriptObject` class with the type tags for all
      // interop types in this module. This is the quick path for simple type
      // tests that matches the rules encoded above.
      var legacyJavaScriptObjectClass = _coreTypes.index
          .getClass('dart:_interceptors', 'LegacyJavaScriptObject');
      var legacyJavaScriptObjectClassRef = _emitClassRef(
          legacyJavaScriptObjectClass.getThisType(
              _coreTypes, Nullability.nonNullable));
      var interopRecipesArray = js_ast.stringArray([
        _typeRecipeGenerator.interfaceTypeRecipe(legacyJavaScriptObjectClass),
        ...jsInteropTypeRecipes
      ]);
      var jsInteropRules = _runtimeStatement('addRtiResources(#, #)',
          [legacyJavaScriptObjectClassRef, interopRecipesArray]);
      _moduleItems.add(jsInteropRules);
    }

    // Annotates the type parameter variances for each interface.
    var typeVariances = _typeRecipeGenerator.variances;
    if (typeVariances.isNotEmpty) {
      var addTypeParameterVariancesTemplate = '#._Universe.#(#, JSON.parse(#))';
      var addTypeParameterVariancesStatement =
          js.call(addTypeParameterVariancesTemplate, [
        _emitLibraryName(_rtiLibrary),
        _emitMemberName('addTypeParameterVariances',
            memberClass: universeClass),
        _runtimeCall('typeUniverse'),
        js.string(jsonEncode(typeVariances), "'")
      ]).toStatement();
      _moduleItems.add(addTypeParameterVariancesStatement);
    }

    // Certain RTIs must be emitted during RTI normalization. We cache these
    // eagerly with 'findType' (without normalization) to avoid infinite loops.
    // See normalization functions in: sdk/lib/_internal/js_shared/lib/rti.dart
    if (_isBuildingSdk) {
      var prerequisiteRtiTypes = [
        _coreTypes.objectLegacyRawType,
        _coreTypes.objectNullableRawType,
        NeverType.legacy()
      ];
      prerequisiteRtiTypes.forEach((type) {
        var recipe = _typeRecipeGenerator
            .recipeInEnvironment(type, EmptyTypeEnvironment())
            .recipe;
        _moduleItems.add(js.call('#.findType("$recipe")',
            [_emitLibraryName(_rtiLibrary)]).toStatement());
      });
    }

    // Visit directives (for exports)
    libraries.forEach(_emitExports);
    _ticker?.logMs('Emitted exports');

    // Declare imports and extension symbols
    _emitImportsAndExtensionSymbols(items,
        forceExtensionSymbols:
            libraries.any((l) => allowedNativeTest(l.importUri)));
    _ticker?.logMs('Emitted imports and extension symbols');

    // Insert a check that runs when loading this module to verify that the null
    // safety mode it was compiled in matches the mode used when compiling the
    // dart sdk module.
    //
    // This serves as a sanity check at runtime that we don't have an
    // infrastructure issue that loaded js files compiled with different modes
    // into the same application.
    js_ast.LiteralBool soundNullSafety;
    switch (component.mode) {
      case NonNullableByDefaultCompiledMode.Strong:
        soundNullSafety = js_ast.LiteralBool(true);
      case NonNullableByDefaultCompiledMode.Weak:
        soundNullSafety = js_ast.LiteralBool(false);
      default:
        throw StateError('Unsupported Null Safety mode ${component.mode}, '
            'in ${component.location?.file}.');
    }
    if (!_isBuildingSdk) {
      items.add(_runtimeStatement(
          '_checkModuleNullSafetyMode(#)', [soundNullSafety]));
    }

    // Emit the hoisted type table cache variables
    items.addAll(_typeTable.dischargeBoundTypes());
    _ticker?.logMs('Emitted type table');

    var module = _finishModule(items, _options.moduleName,
        header: _generateCompilationHeader());
    _ticker?.logMs('Finished emitting module');

    // Mark as finished for incremental mode, so it is safe to
    // switch to the incremental mode for expression compilation.
    _moduleEmitted = true;
    return module;
  }

  /// Choose a canonical name from the [library] element.
  String _jsLibraryName(Library library) {
    return libraryUriToJsIdentifier(library.importUri);
  }

  /// Choose a module-unique name from the [library] element.
  ///
  /// Returns null if no alias exists or there are multiple output paths
  /// (e.g., when compiling the Dart SDK).
  ///
  /// This never uses the library's name (the identifier in the `library`
  /// declaration) as it doesn't have any meaningful rules enforced.
  String? _jsLibraryAlias(Library library) {
    var uri = library.importUri.normalizePath();
    if (uri.isScheme('dart')) return null;

    Iterable<String> segments;
    if (uri.isScheme('package')) {
      // Strip the package name.
      segments = uri.pathSegments.skip(1);
    } else {
      segments = uri.pathSegments;
    }

    var qualifiedPath =
        js_ast.pathToJSIdentifier(p.withoutExtension(segments.join('/')));
    return qualifiedPath == _jsLibraryName(library) ? null : qualifiedPath;
  }

  /// Debugger friendly name for a Dart [library].
  String _jsLibraryDebuggerName(Library library) => '${library.importUri}';

  /// Debugger friendly names for all parts in a Dart [library].
  Iterable<String> _jsPartDebuggerNames(Library library) =>
      library.parts.map((part) => part.partUri);

  /// True when [library] is the sdk internal library 'dart:_internal'.
  bool _isDartInternal(Library library) => _isDartLibrary(library, '_internal');

  /// True when [library] is the sdk internal library 'dart:_js_helper'.
  bool _isDartJsHelper(Library library) =>
      _isDartLibrary(library, '_js_helper');

  /// True when [library] is the sdk internal library 'dart:_internal'.
  bool _isDartForeignHelper(Library library) =>
      _isDartLibrary(library, '_foreign_helper');

  /// True when [library] is the sdk library 'dart:js_util'.
  bool _isDartJsUtil(Library library) => _isDartLibrary(library, 'js_util');

  /// Returns true if [library] is identified by [name].
  bool _isDartLibrary(Library library, String name) {
    var importUri = library.importUri;
    return importUri.isScheme('dart') && importUri.path == name;
  }

  /// Returns true if the library [l] is "dart:_runtime".
  bool _isSdkInternalRuntime(Library l) {
    return isSdkInternalRuntimeUri(l.importUri);
  }

  /// Gets the module import URI that contains [library].
  String _libraryToModule(Library library, {bool throwIfNotFound = true}) {
    if (library.importUri.isScheme('dart')) {
      // TODO(jmesserly): we need to split out HTML.
      return js_ast.dartSdkModule;
    }
    var summary = _importToSummary[library];
    if (summary == null) {
      if (throwIfNotFound) {
        throw StateError('Could not find summary for library "$library".');
      }
      return '';
    }
    var moduleName = _summaryToModule[summary];
    if (moduleName == null) {
      if (throwIfNotFound) {
        throw StateError('Could not find module name for library "$library" '
            'from component "$summary".');
      }
      return '';
    }
    return moduleName;
  }

  void _emitLibrary(Library library) {
    // NOTE: this method isn't the right place to initialize per-library state.
    // Classes can be visited out of order, so this is only to catch things that
    // haven't been emitted yet.
    //
    // See _emitClass.
    assert(_currentLibrary == null);
    _currentLibrary = library;
    _staticTypeContext.enterLibrary(_currentLibrary!);

    if (_isBuildingSdk) {
      _containerizeSymbols = _isWebLibrary(library.importUri);
    }

    if (_isSdkInternalRuntime(library)) {
      // Add embedded globals.
      _moduleItems.add(
          _runtimeCall('typeUniverse = #', [js_ast.createRtiUniverse()])
              .toStatement());
      // `dart:_runtime` uses a different order for bootstrapping.
      //
      // Functions are first because we use them to associate type info
      // (such as `dart.fn`), then classes/typedefs, then fields
      // (which instantiate classes).
      //
      // For other libraries, we start with classes/types, because functions
      // often use classes/types from the library in their signature.
      //
      // TODO(jmesserly): we can merge these once we change signatures to be
      // lazily associated at the tear-off point for top-level functions.
      _emitLibraryProcedures(library);
      _emitTopLevelFields(library.fields);
      library.classes.forEach(_emitClass);
    } else {
      library.classes.forEach(_emitClass);
      _emitLibraryProcedures(library);
      _emitTopLevelFields(library.fields);
    }
    _staticTypeContext.leaveLibrary(_currentLibrary!);
    _currentLibrary = null;
  }

  void _emitExports(Library library) {
    assert(_currentLibrary == null);
    _currentLibrary = library;

    library.additionalExports.forEach(_emitExport);

    _currentLibrary = null;
  }

  void _emitExport(Reference export) {
    var library = _currentLibrary!;

    // We only need to export main as it is the only method part of the
    // publicly exposed JS API for a library.

    var node = export.node;
    if (node is Procedure && node.name.text == 'main') {
      // Don't allow redefining names from this library.
      var name = _emitTopLevelName(node);
      _moduleItems.add(js.statement(
          '#.# = #;', [_emitLibraryName(library), name.selector, name]));
    }
  }

  /// Called to emit class declarations.
  ///
  /// During the course of emitting one item, we may emit another. For example
  ///
  ///     class D extends B { C m() { ... } }
  ///
  /// Because D depends on B, we'll emit B first if needed. However C is not
  /// used by top-level JavaScript code, so we can ignore that dependency.
  void _emitClass(Class c) {
    if (!_pendingClasses!.remove(c)) return;

    var savedClass = _currentClass;
    var savedLibrary = _currentLibrary;
    var savedUri = _currentUri;
    _currentClass = c;
    _currentLibrary = c.enclosingLibrary;
    _currentUri = c.fileUri;
    var savedTypeEnvironment = _currentTypeEnvironment;
    // When compiling the type heritage of the class we can't reference an rti
    // object attached to an instance. Instead we construct a type environment
    // manually when needed. Later we use the rti attached to an instance for
    // a simpler representation within instance members of the class.
    _currentTypeEnvironment = ClassTypeEnvironment(c.typeParameters);

    // Mixins are unrolled in _defineClass.
    if (!c.isAnonymousMixin) {
      // If this class is annotated with `@JS`, then we only need to emit the
      // non-external factories and static members.
      if (!hasJSInteropAnnotation(c)) {
        _moduleItems.add(_emitClassDeclaration(c));
      } else {
        var interopClassDef = _emitJSInteropClassNonExternalMembers(c);
        if (interopClassDef != null) _moduleItems.add(interopClassDef);
      }
    }

    // The const table depends on dart.defineLazy, so emit it after the SDK.
    if (_isSdkInternalRuntime(_currentLibrary!)) {
      _constTableInsertionIndex = _moduleItems.length;
    }

    _currentClass = savedClass;
    _currentLibrary = savedLibrary;
    _currentUri = savedUri;
    _currentTypeEnvironment = savedTypeEnvironment;
  }

  /// To emit top-level classes, we sometimes need to reorder them.
  ///
  /// This function takes care of that, and also detects cases where reordering
  /// failed, and we need to resort to lazy loading, by marking the element as
  /// lazy. All elements need to be aware of this possibility and generate code
  /// accordingly.
  ///
  /// If we are not emitting top-level code, this does nothing, because all
  /// declarations are assumed to be available before we start execution.
  /// See [startTopLevel].
  void _declareBeforeUse(Class? c) {
    if (c != null && _emittingClassExtends) {
      _emitClass(c);
    }
  }

  static js_ast.Identifier _emitIdentifier(String name) =>
      js_ast.Identifier(js_ast.toJSIdentifier(name));

  static js_ast.ScopedId _emitScopedId(String name,
          {bool needsCapture = false}) =>
      js_ast.ScopedId(js_ast.toJSIdentifier(name), needsCapture: needsCapture);

  js_ast.Statement _emitClassDeclaration(Class c) {
    var className = _emitTopLevelNameNoExternalInterop(c);
    var savedClassProperties = _classProperties;
    _classProperties =
        ClassPropertyModel.build(_types, _extensionTypes, _virtualFields, c);

    var body = <js_ast.Statement>[];

    // ClassPropertyModel.build introduces symbols for virtual field accessors.
    _classProperties!.virtualFields.forEach((field, virtualField) {
      // TODO(vsm): Clean up this logic.
      //
      // Typically, [emitClassPrivateNameSymbol] creates a new symbol.  If it
      // is called multiple times, that symbol is cached.  If the former,
      // assign directly to [virtualField].  If the latter, copy the old
      // variable to [virtualField].
      var symbol = _emitClassPrivateNameSymbol(
          c.enclosingLibrary, getLocalClassName(c), field, virtualField);
      if (symbol != virtualField) {
        _addSymbol(virtualField, _getSymbolValue(symbol));
        if (!_containerizeSymbols) {
          body.add(js.statement('const # = #;', [virtualField, symbol]));
        }
      }
    });

    var jsCtors = _defineConstructors(c, className);

    var jsMethods = _emitClassMethods(c);

    _emitSuperHelperSymbols(body);
    // Deferred supertypes must be evaluated lazily while emitting classes to
    // prevent evaluating a JS expression for a deferred type from influencing
    // class declaration order (such as when calling 'emitDeferredType').
    var deferredSupertypes = <js_ast.Statement Function()>[];

    // Emit the class, e.g. `core.Object = class Object { ... }`
    _defineClass(c, className, jsMethods, body, deferredSupertypes);
    body.addAll(jsCtors);

    // Emit things that come after the ES6 `class ... { ... }`.

    /// Collects all implemented types in the ancestry of [cls].
    Iterable<Supertype> transitiveImplementedTypes(Class cls) {
      var allImplementedTypes = <Supertype>{};
      var toVisit = ListQueue<Supertype>()..addAll(cls.implementedTypes);
      if (cls.isMixinApplication) {
        // Implemented types can come through the immediate mixin so we seed
        // the search with it as well.
        var mixedInType = cls.mixedInType;
        if (mixedInType != null) toVisit.add(mixedInType);
      }
      while (toVisit.isNotEmpty) {
        var supertype = toVisit.removeFirst();
        var superclass = supertype.classNode;
        if (allImplementedTypes.contains(supertype) ||
            superclass == _coreTypes.objectClass) {
          continue;
        }
        toVisit.addAll(superclass.supers);
        // Skip encoding the synthetic classes in the type rules because they
        // will never be instantiated or appear in type tests.
        if (superclass.isAnonymousMixin) continue;
        allImplementedTypes.add(supertype);
      }
      return allImplementedTypes;
    }

    // Tag all classes with the resources needed by the dart:_rti library.
    var name = _typeRecipeGenerator.interfaceTypeRecipe(c);
    var implementedRecipes = [
      name,
      for (var type in transitiveImplementedTypes(c))
        _typeRecipeGenerator.interfaceTypeRecipe(type.classNode)
    ];
    body.add(_runtimeStatement('addRtiResources(#, #)',
        [className, js_ast.stringArray(implementedRecipes)]));
    _emitClassSignature(c, className, body);
    _initExtensionSymbols(c);
    if (!c.isMixinDeclaration) {
      _defineExtensionMembers(className, body);
    }

    var typeFormals = c.typeParameters;
    var evaluatedDeferredSupertypes =
        deferredSupertypes.map<js_ast.Statement>((f) => f()).toList();
    if (typeFormals.isNotEmpty) {
      var genericClassStmts = _defineGenericClass(typeFormals,
          js_ast.Statement.from(body), evaluatedDeferredSupertypes);
      body = [...genericClassStmts];
    } else {
      _afterClassDefItems.addAll(evaluatedDeferredSupertypes);
    }

    _emitStaticFieldsAndAccessors(c, body);
    if (c == _coreTypes.objectClass) {
      // Avoid polluting the native JavaScript Object prototype with the members
      // of the Dart Core Object class.
      // Instead, just assign the identity equals method.
      body.add(_runtimeStatement('_installIdentityEquals()'));
    } else {
      for (var peer in _extensionTypes.getNativePeers(c)) {
        _registerExtensionType(c, peer, body);
      }
    }
    _classProperties = savedClassProperties;
    return js_ast.Statement.from(body);
  }

  /// Emits a class declaration for the JS interop class [c] for any
  /// non-external factories or static members.
  ///
  /// If [c] is not an interop class or does not contain non-external factories
  /// or static members, returns null.
  js_ast.Statement? _emitJSInteropClassNonExternalMembers(Class c) {
    if (!hasJSInteropAnnotation(c)) return null;
    var className = _emitTopLevelNameNoExternalInterop(c);

    var nonExternalMethods = <js_ast.Method>[];
    for (var procedure in c.procedures) {
      if (procedure.isExternal) continue;
      // Don't emit tear-offs for @staticInterop members as they're disallowed.
      if (_isStaticInteropTearOff(procedure)) continue;
      if (procedure.isFactory && !procedure.isRedirectingFactory) {
        // Skip redirecting factories (they've already been resolved).
        var factory = _emitFactoryConstructor(procedure);
        if (factory != null) nonExternalMethods.add(factory);
      } else if (procedure.isStatic) {
        var staticMethod = _emitMethodDeclaration(procedure);
        if (staticMethod != null) nonExternalMethods.add(staticMethod);
      }
    }

    // Emit static fields, if there are any.
    var fieldInitialization = <js_ast.Statement>[];
    _emitStaticFieldsAndAccessors(c, fieldInitialization);

    // Avoid unnecessary code emission if there are no members we care about.
    if (nonExternalMethods.isNotEmpty || fieldInitialization.isNotEmpty) {
      // Note that this class has no heritage. This class should never be used
      // as a type. It's merely a placeholder for static members.
      var body = <js_ast.Statement>[
        _emitClassStatement(c, className, null, nonExternalMethods)
            .toStatement()
      ];
      var typeFormals = c.typeParameters;
      if (typeFormals.isNotEmpty) {
        var genericClassStmts =
            _defineGenericClass(typeFormals, js_ast.Statement.from(body), []);
        body = [...genericClassStmts, ...fieldInitialization];
      } else {
        body = [...body, ...fieldInitialization];
      }
      return js_ast.Statement.from(body);
    }
    return null;
  }

  /// Emits a generic class with additional initialization logic.
  List<js_ast.Statement> _defineGenericClass(List<TypeParameter> formals,
      js_ast.Statement body, List<js_ast.Statement> deferredBaseClass) {
    assert(formals.isNotEmpty);
    return [
      ..._typeTable.dischargeFreeTypes(formals),
      body,
      ...deferredBaseClass,
    ];
  }

  js_ast.Statement _emitClassStatement(Class c, js_ast.Expression className,
      js_ast.Expression? heritage, List<js_ast.Method> methods) {
    var classIdentifier = _emitScopedId(getLocalClassName(c));
    if (_options.emitDebugSymbols) classIdentifiers[c] = classIdentifier;
    var classExpr = js_ast.ClassExpression(classIdentifier, heritage, methods);
    return js.statement('# = #;', [className, classExpr]);
  }

  /// Like [_emitClassStatement] but emits a Dart 2.1 mixin represented by
  /// [c].
  ///
  /// Mixins work similar to normal classes, but their instance methods close
  /// over the actual superclass. Given a Dart class like:
  ///
  ///     mixin M on C {
  ///       foo() => super.foo() + 42;
  ///     }
  ///
  /// We generate a JS class like this:
  ///
  ///     lib.M = class M extends core.Object {}
  ///     lib.M[dart.mixinOn] = (C) => class M extends C {
  ///       foo() {
  ///         return super.foo() + 42;
  ///       }
  ///     };
  ///
  /// The special `dart.mixinOn` symbolized property is used by the runtime
  /// helper `dart.applyMixin`. The helper calls the function with the actual
  /// base class, and then copies the resulting members to the destination
  /// class.
  ///
  /// In the long run we may be able to improve this so we do not have the
  /// unnecessary class, but for now, this lets us get the right semantics with
  /// minimal compiler and runtime changes.
  void _emitMixinStatement(
      Class c,
      js_ast.Expression className,
      js_ast.Expression heritage,
      List<js_ast.Method> methods,
      List<js_ast.Statement> body) {
    var staticMethods = methods.where((m) => m.isStatic).toList();
    var instanceMethods = methods.where((m) => !m.isStatic).toList();

    body.add(_emitClassStatement(c, className, heritage, staticMethods));
    var superclassId = _emitScopedId(getLocalClassName(c.superclass!));
    var classId = className is js_ast.Identifier
        ? className
        : _emitScopedId(getLocalClassName(c));

    var mixinMemberClass =
        js_ast.ClassExpression(classId, superclassId, instanceMethods);

    js_ast.Node arrowFnBody = mixinMemberClass;
    var extensionInit = <js_ast.Statement>[];
    _defineExtensionMembers(classId, extensionInit);
    if (extensionInit.isNotEmpty) {
      extensionInit.insert(0, mixinMemberClass.toStatement());
      extensionInit.add(classId.toReturn());
      arrowFnBody = js_ast.Block(extensionInit);
    }

    body.add(js.statement('#[#] = #', [
      className,
      _runtimeCall('mixinOn'),
      js_ast.ArrowFun([superclassId], arrowFnBody)
    ]));
  }

  void _defineClass(
      Class c,
      js_ast.Expression className,
      List<js_ast.Method> methods,
      List<js_ast.Statement> body,
      List<js_ast.Statement Function()> deferredSupertypes) {
    if (c == _coreTypes.objectClass) {
      body.add(_emitClassStatement(c, className, null, methods));
      return;
    }

    js_ast.Expression emitDeferredClassRef(InterfaceType type) {
      var savedEmittingDeferredType = _emittingDeferredType;
      _emittingDeferredType = true;
      _declareBeforeUse(type.classNode);
      var deferredClassRef = _emitClassRef(type);
      _emittingDeferredType = savedEmittingDeferredType;
      return deferredClassRef;
    }

    bool shouldDefer(InterfaceType type) {
      var visited = <DartType>{};
      bool defer(InterfaceType t) {
        var tc = t.classNode;
        if (c == tc) return true;
        if (tc == _coreTypes.objectClass || !visited.add(t)) return false;
        var mixin = tc.mixedInType;
        return mixin != null && defer(mixin.asInterfaceType) ||
            defer(tc.supertype!.asInterfaceType);
      }

      return defer(type);
    }

    js_ast.Expression emitClassRef(InterfaceType t) {
      // TODO(jmesserly): investigate this. It seems like `lazyJSType` is
      // invalid for use in an `extends` clause, hence this workaround.
      return _emitJSInterop(t.classNode) ?? _emitClassRef(t);
    }

    js_ast.Expression getBaseClass(int count) {
      var base = emitDeferredClassRef(
          c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable));
      while (--count >= 0) {
        base = _emitJSObjectGetPrototypeOf(base, fullyQualifiedName: true);
      }
      return base;
    }

    // Find the real (user declared) superclass and the list of mixins.
    // We'll use this to unroll the intermediate classes.
    //
    // TODO(jmesserly): consider using Kernel's mixin unrolling.
    var superclass = _superClassAsWritten(c);
    var supertype = identical(c.superclass, superclass)
        ? c.supertype!.asInterfaceType
        : _hierarchy.getClassAsInstanceOf(c, superclass)!.asInterfaceType;
    // All mixins (real and anonymous) classes applied to c.
    var mixinApplications = [
      if (c.mixedInClass != null) c.mixedInClass,
      for (var sc = c.superclass!;
          sc.isAnonymousMixin && sc.mixedInClass != null;
          sc = sc.superclass!)
        sc,
    ].reversed.toList();

    var hasUnnamedSuper = _hasUnnamedInheritedConstructor(superclass);

    void emitMixinConstructors(js_ast.Expression className,
        Class mixinSuperclass, Class mixinClass, InterfaceType mixin) {
      for (var ctor in mixinSuperclass.constructors) {
        var savedUri = _currentUri;
        _currentUri = ctor.enclosingClass.fileUri;

        var sharedParams = _emitParameters(ctor.function, isForwarding: true);
        var mixinConstructorParams = [
          if (_requiresRtiForInstantiation(mixinSuperclass)) _rtiParam,
          ...sharedParams
        ];
        var superConstructorArgs = [
          if (_requiresRtiForInstantiation(ctor.enclosingClass))
            js_ast.LiteralNull(),
          ...sharedParams
        ];

        js_ast.Statement? mixinCtor;
        if (_hasUnnamedConstructor(mixin.classNode)) {
          var mixinRti = _requiresRtiForInstantiation(mixin.classNode)
              ? js_ast.LiteralNull()
              : null;
          mixinCtor = js.statement('#.#.call(this, #);', [
            emitClassRef(mixin),
            _usesMixinNew(mixin.classNode)
                ? _runtimeCall('mixinNew')
                : _constructorName(''),
            [if (mixinRti != null) mixinRti],
          ]);
        }

        var name = ctor.name.text;
        var ctorBody = [
          if (mixinCtor != null) mixinCtor,
          if (name != '' || hasUnnamedSuper)
            _emitSuperConstructorCall(
                ctor, className, name, superConstructorArgs),
        ];
        // TODO(nshahan) Record the name for this constructor in memberNames.
        body.add(_addConstructorToClass(c, className, _constructorName(name),
            js_ast.Fun(mixinConstructorParams, js_ast.Block(ctorBody))));
        _currentUri = savedUri;
      }
    }

    var savedTopLevelClass = _classEmittingExtends;
    _classEmittingExtends = c;

    // Unroll mixins.
    var baseClass = shouldDefer(supertype)
        ? emitDeferredClassRef(supertype)
        : emitClassRef(supertype);

    // TODO(jmesserly): we need to unroll kernel mixins because the synthetic
    // classes lack required synthetic members, such as constructors.
    //
    // Also, we need to generate one extra level of nesting for alias classes.
    for (var i = 0; i < mixinApplications.length; i++) {
      var m = mixinApplications[i]!;
      var mixinClass = m.isAnonymousMixin ? m.mixedInClass! : m;
      _declareBeforeUse(mixinClass);
      var mixinType =
          _hierarchy.getClassAsInstanceOf(c, mixinClass)!.asInterfaceType;
      var mixinName =
          '${getLocalClassName(superclass)}_${getLocalClassName(mixinClass)}';
      var mixinId = _emitScopedId('$mixinName\$');
      // Collect all forwarding stub members from anonymous mixins classes.
      // These can contain covariant parameter checks that need to be applied.
      var savedClassProperties = _classProperties;
      _classProperties =
          ClassPropertyModel.build(_types, _extensionTypes, _virtualFields, m);
      var forwardingMembers = {
        for (var procedure in m.procedures)
          if (procedure.isForwardingStub && !procedure.isAbstract)
            procedure.name.text: procedure
      };
      // Mixin applications can introduce their own reference to the type
      // parameters from the class being mixed in and their use can appear in
      // the forwarding stubs.
      var savedTypeEnvironment = _currentTypeEnvironment;
      if (m.typeParameters.isNotEmpty) {
        assert(_currentTypeEnvironment is ClassTypeEnvironment);
        _currentTypeEnvironment = ClassTypeEnvironment(m.typeParameters);
      }
      var forwardingMethodStubs = <js_ast.Method>[];
      for (var s in forwardingMembers.values) {
        // Members are marked as "forwarding stubs" when they require a type
        // check of the arguments before calling super. It is assumed here that
        // no getters will be marked as a "forwarding stub".
        assert(!s.isGetter);
        var stub = _emitMethodDeclaration(s);
        if (stub != null) forwardingMethodStubs.add(stub);
        // If there are getters matching the setters somewhere above in the
        // class hierarchy we must also generate a forwarding getter due to the
        // representation used in the compiled JavaScript.
        if (s.isSetter) {
          var getterWrapper = _emitSuperAccessorWrapper(s, const {}, const {});
          if (getterWrapper != null) forwardingMethodStubs.add(getterWrapper);
        }
      }
      _currentTypeEnvironment = savedTypeEnvironment;
      _classProperties = savedClassProperties;

      // Bind the mixin class to a name to workaround a V8 bug with es6 classes
      // and anonymous function names.
      // TODO(leafp:) Eliminate this once the bug is fixed:
      // https://bugs.chromium.org/p/v8/issues/detail?id=7069
      body.add(js.statement('const # = #', [
        mixinId,
        js_ast.ClassExpression(
            _emitScopedId(mixinName), baseClass, forwardingMethodStubs)
      ]));

      emitMixinConstructors(mixinId, superclass, mixinClass, mixinType);
      hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(mixinClass);

      if (shouldDefer(mixinType)) {
        deferredSupertypes.add(() => _runtimeStatement('applyMixin(#, #)', [
              getBaseClass(mixinApplications.length - i),
              emitDeferredClassRef(mixinType)
            ]));
      } else {
        body.add(_runtimeStatement(
            'applyMixin(#, #)', [mixinId, emitClassRef(mixinType)]));
      }

      baseClass = mixinId;
    }

    if (c.isMixinDeclaration && !c.isMixinClass) {
      _emitMixinStatement(c, className, baseClass, methods, body);
    } else {
      body.add(_emitClassStatement(c, className, baseClass, methods));
    }

    _classEmittingExtends = savedTopLevelClass;
  }

  /// Defines all constructors for this class as ES5 constructors.
  List<js_ast.Statement> _defineConstructors(
      Class c, js_ast.Expression className) {
    var body = <js_ast.Statement>[];
    if (c.isAnonymousMixin) {
      // We already handled this when we defined the class.
      return body;
    }

    void addConstructor(js_ast.LiteralString name, js_ast.Expression jsCtor) {
      body.add(_addConstructorToClass(c, className, name, jsCtor));
    }

    var fields = c.fields;
    for (var ctor in c.constructors) {
      if (ctor.isExternal) continue;
      var constructorName = _constructorName(ctor.name.text);
      memberNames[ctor] = constructorName.valueWithoutQuotes;
      addConstructor(
          constructorName, _emitConstructor(ctor, fields, className));
    }

    // If classElement has only factory constructors, and it can be mixed in,
    // then we need to emit a special hidden default constructor for use by
    // mixins.
    if (_usesMixinNew(c)) {
      body.add(
          js.statement('(#[#] = function() { # }).prototype = #.prototype;', [
        className,
        _runtimeCall('mixinNew'),
        [_initializeFields(fields)],
        className
      ]));
    }

    return body;
  }

  void _emitDartSymbols(
      Iterable<js_ast.ScopedId> vars, List<js_ast.ModuleItem> body) {
    for (var id in vars) {
      body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
    }
  }

  void _emitSuperHelperSymbols(List<js_ast.Statement> body) {
    _emitDartSymbols(
        _superHelpers.values.map((m) => m.name as js_ast.ScopedId), body);
    _superHelpers.clear();
  }

  /// Emits non-external static fields for a class, and initialize them eagerly
  /// if possible, otherwise define them as lazy properties.
  void _emitStaticFieldsAndAccessors(Class c, List<js_ast.Statement> body) {
    var fields = c.fields.where((f) => f.isStatic && !f.isExternal).toList();
    var fieldNames = Set.of(fields.map((f) => f.name));
    var staticSetters = c.procedures.where(
        (p) => p.isStatic && p.isAccessor && fieldNames.contains(p.name));
    var members = [...fields, ...staticSetters];
    if (fields.isNotEmpty) {
      body.add(_emitLazyMembers(_emitTopLevelNameNoExternalInterop(c), members,
          (n) => _emitStaticMemberName(n.name.text)));
    }
  }

  /// Ensure `dartx.` symbols we will use are present.
  void _initExtensionSymbols(Class c) {
    if (_extensionTypes.hasNativeSubtype(c) || c == _coreTypes.objectClass) {
      for (var m in c.procedures) {
        if (!m.isAbstract && !m.isStatic && !m.name.isPrivate) {
          _declareMemberName(m, useExtension: true);
        }
      }
    }
  }

  /// If a concrete class implements one of our extensions, we might need to
  /// add forwarders.
  void _defineExtensionMembers(
      js_ast.Expression className, List<js_ast.Statement> body) {
    void emitExtensions(String helperName, Iterable<String> extensions) {
      if (extensions.isEmpty) return;
      var names = extensions
          .map((e) => _propertyName(js_ast.memberNameForDartMember(e)))
          .toList();
      body.add(_runtimeStatement('#(#, #)', [
        helperName,
        className,
        js_ast.ArrayInitializer(names, multiline: names.length > 4)
      ]));
    }

    var props = _classProperties!;
    emitExtensions('defineExtensionMethods', props.extensionMethods);
    emitExtensions('defineExtensionAccessors', props.extensionAccessors);
  }

  /// Emit the signature on the class recording the runtime type information
  void _emitClassSignature(
      Class c, js_ast.Expression className, List<js_ast.Statement> body) {
    var savedTypeEnvironment = _currentTypeEnvironment;
    _currentTypeEnvironment =
        RtiTypeEnvironment(_currentTypeEnvironment.classTypeParameters);
    var savedClass = _classEmittingSignatures;
    _classEmittingSignatures = c;

    void emitSignature(String name, List<js_ast.Property> elements) {
      if (elements.isEmpty) return;

      js_ast.Statement setSignature;
      if (!name.startsWith('Static')) {
        var proto = c == _coreTypes.objectClass
            ? js.call('Object.create(null)')
            : _runtimeCall('get${name}s(#)', [
                _emitJSObjectGetPrototypeOf(className, fullyQualifiedName: true)
              ]);

        setSignature = _runtimeStatement('set${name}Signature(#, () => #)', [
          className,
          _emitJSObjectSetPrototypeOf(
              js_ast.ObjectInitializer(elements,
                  multiline: elements.length > 1),
              proto,
              fullyQualifiedName: true)
        ]);
      } else {
        // TODO(40273) Only tagging with the names of static members until the
        // debugger consumes signature information from symbol files.
        setSignature = _runtimeStatement('set${name}Signature(#, () => #)', [
          className,
          js_ast.ArrayInitializer(elements.map((e) => e.name).toList())
        ]);
      }

      body.add(setSignature);
    }

    js_ast.Expression emitClassFieldSignature(Field field, Class fromClass) {
      var fieldType =
          _typeFromClass(field.type, field.enclosingClass!, fromClass)
              .extensionTypeErasure;
      var uri = fieldType is InterfaceType
          ? _cacheUri(
              _jsLibraryDebuggerName(fieldType.classNode.enclosingLibrary))
          : null;
      var isConst = js.boolean(field.isConst);
      var isFinal = js.boolean(field.isFinal);
      var type = _emitType(fieldType);
      var typeResolver = js_ast.ArrowFun([_rtiParam], type);
      return uri == null
          ? js('{type: #, isConst: #, isFinal: #}',
              [typeResolver, isConst, isFinal])
          : js('{type: #, isConst: #, isFinal: #, libraryUri: #}',
              [typeResolver, isConst, isFinal, uri]);
    }

    var extMethods = _classProperties!.extensionMethods;
    var extAccessors = _classProperties!.extensionAccessors;
    var staticMethods = <js_ast.Property>[];
    var instanceMethods = <js_ast.Property>[];
    var instanceMethodsDefaultTypeArgs = <js_ast.Property>[];
    var staticGetters = <js_ast.Property>[];
    var instanceGetters = <js_ast.Property>[];
    var staticSetters = <js_ast.Property>[];
    var instanceSetters = <js_ast.Property>[];
    List<js_ast.Property> getSignatureList(Procedure p) {
      // TODO(40273) Skip for all statics when the debugger consumes signature
      // information from symbol files.
      if (p.isStatic) {
        if (p.isGetter) {
          return staticGetters;
        } else if (p.isSetter) {
          return staticSetters;
        } else {
          return staticMethods;
        }
      } else {
        if (p.isGetter) {
          return instanceGetters;
        } else if (p.isSetter) {
          return instanceSetters;
        } else {
          return instanceMethods;
        }
      }
    }

    var classProcedures = c.procedures.where((p) => !p.isAbstract).toList();
    for (var member in classProcedures) {
      // Static getters/setters cannot be called with dynamic dispatch or torn
      // off. Static methods can't be called with dynamic dispatch and are
      // tagged with a type when torn off. Most are implicitly const and
      // canonicalized. Static signatures are only used by the debugger and are
      // not needed for runtime correctness.
      // TODO(40273) Skip for all statics when the debugger consumes signature
      // information from symbol files.
      if (isTearOffLowering(member)) continue;

      var name = member.name.text;
      var reifiedType = _memberRuntimeType(member, c) as FunctionType;

      // Don't add redundant signatures for inherited methods whose signature
      // did not change.  If we are not overriding, or if the thing we are
      // overriding has a different reified type from ourselves, we must
      // emit a signature on this class.  Otherwise we will inherit the
      // signature from the superclass.
      var memberOverride = c.superclass != null
          ? _hierarchy.getDispatchTarget(c.superclass!, member.name,
              setter: member.isSetter)
          : null;

      var needsSignature = memberOverride == null ||
          reifiedType != _memberRuntimeType(memberOverride, c);

      if (needsSignature) {
        js_ast.Expression type;
        var memberName = _declareMemberName(member);
        if (member.isAccessor) {
          // These signatures are used for dynamic access and to inform the
          // debugger. The `arrayRti` accessor is only used by the dart:_rti
          // library internals and should not be included in the accessible
          // signatures.
          if (c == _jsArrayClass && name == 'arrayRti') continue;
          type = _emitType(member.isGetter
              ? reifiedType.returnType
              : reifiedType.positionalParameters[0]);
        } else {
          type = _emitType(reifiedType);
          if (!member.isStatic && reifiedType.typeParameters.isNotEmpty) {
            // Instance methods with generic type parameters require extra
            // information to support dynamic calls. The default values for the
            // type parameters are encoded into a separate storage object for
            // use at runtime.
            var defaultTypeArgs = js_ast.ArrayInitializer([
              for (var parameter in reifiedType.typeParameters)
                _emitType(parameter.defaultType)
            ]);
            var typeResolver = js_ast.ArrowFun([_rtiParam], defaultTypeArgs);
            var property = js_ast.Property(memberName, typeResolver);
            instanceMethodsDefaultTypeArgs.add(property);
            // As seen below, sometimes the member signatures are added again
            // using the extension symbol as the name. That logic is duplicated
            // here to ensure there are always default type arguments accessible
            // via the same name as the signature.
            // TODO(52867): Cleanup default type argument duplication.
            if (extMethods.contains(name) || extAccessors.contains(name)) {
              var property = js_ast.Property(
                  _declareMemberName(member, useExtension: true), typeResolver);
              instanceMethodsDefaultTypeArgs.add(property);
            }
          }
        }
        var typeResolver = js_ast.ArrowFun([_rtiParam], type);
        var property = js_ast.Property(memberName, typeResolver);
        var signatures = getSignatureList(member);
        signatures.add(property);
        if (!member.isStatic &&
            (extMethods.contains(name) || extAccessors.contains(name))) {
          // TODO(52867): Cleanup signature duplication.
          var typeResolver = js_ast.ArrowFun([_rtiParam], type);
          var property = js_ast.Property(
              _declareMemberName(member, useExtension: true), typeResolver);
          signatures.add(property);
        }
      }
    }

    emitSignature('Method', instanceMethods);
    emitSignature('MethodsDefaultTypeArg', instanceMethodsDefaultTypeArgs);
    // TODO(40273) Skip for all statics when the debugger consumes signature
    // information from symbol files.
    emitSignature('StaticMethod', staticMethods);
    emitSignature('Getter', instanceGetters);
    emitSignature('Setter', instanceSetters);
    emitSignature('StaticGetter', staticGetters);
    emitSignature('StaticSetter', staticSetters);
    body.add(_runtimeStatement('setLibraryUri(#, #)',
        [className, _cacheUri(_jsLibraryDebuggerName(c.enclosingLibrary))]));

    var instanceFields = <js_ast.Property>[];
    var staticFields = <js_ast.Property>[];

    var classFields = c.fields.toList();
    for (var field in classFields) {
      // Static fields cannot be called with dynamic dispatch or torn off. The
      // signatures are only used by the debugger and are not needed for runtime
      // correctness.
      var memberName = _declareMemberName(field);
      var fieldSig = emitClassFieldSignature(field, c);
      var property = js_ast.Property(memberName, fieldSig);
      // TODO(40273) Skip static fields when the debugger consumes signature
      // information from symbol files.
      (field.isStatic ? staticFields : instanceFields).add(property);
    }
    emitSignature('Field', instanceFields);
    // TODO(40273) Skip for all statics when the debugger consumes signature
    // information from symbol files.
    emitSignature('StaticField', staticFields);
    _classEmittingSignatures = savedClass;
    _currentTypeEnvironment = savedTypeEnvironment;
  }

  DartType _memberRuntimeType(Member member, Class fromClass) {
    var f = member.function;
    if (f == null) {
      return (member as Field).type;
    }
    FunctionType result;
    if (!f.positionalParameters.any(isCovariantParameter) &&
        !f.namedParameters.any(isCovariantParameter)) {
      // Avoid tagging a member as Function? or Function*
      result = f.computeThisFunctionType(Nullability.nonNullable);
    } else {
      var fComputed =
          f.computeThisFunctionType(member.enclosingLibrary.nonNullable);
      var fComputedNamedByName = {
        for (NamedType namedParameter in fComputed.namedParameters)
          namedParameter.name: namedParameter
      };
      DartType reifyParameter(
              VariableDeclaration parameter, DartType fComputedParameter) =>
          isCovariantParameter(parameter)
              ? _coreTypes.objectRawType(member.enclosingLibrary.nullable)
              : fComputedParameter;
      NamedType reifyNamedParameter(
          VariableDeclaration parameter, NamedType fComputedNamedParameter) {
        assert(parameter.name == fComputedNamedParameter.name);
        return NamedType(parameter.name!,
            reifyParameter(parameter, fComputedNamedParameter.type));
      }

      // TODO(jmesserly): do covariant type parameter bounds also need to be
      // reified as `Object`?
      result = FunctionType(
          List<DartType>.generate(
              f.positionalParameters.length,
              (index) => reifyParameter(f.positionalParameters[index],
                  fComputed.positionalParameters[index])),
          f.returnType,
          Nullability.nonNullable,
          namedParameters: List<NamedType>.generate(
              f.namedParameters.length,
              (index) => reifyNamedParameter(f.namedParameters[index],
                  fComputedNamedByName[f.namedParameters[index].name]!))
            ..sort(),
          typeParameters: fComputed.typeParameters,
          requiredParameterCount: f.requiredParameterCount);
    }
    return _typeFromClass(result, member.enclosingClass!, fromClass)
        as FunctionType;
  }

  DartType _typeFromClass(DartType type, Class superclass, Class subclass) {
    if (identical(superclass, subclass)) return type;
    return Substitution.fromSupertype(
            _hierarchy.getClassAsInstanceOf(subclass, superclass)!)
        .substituteType(type);
  }

  js_ast.Expression _emitConstructor(
      Constructor node, List<Field> fields, js_ast.Expression className) {
    var savedUri = _currentUri;
    _currentUri = node.fileUri;
    _staticTypeContext.enterMember(node);
    var savedTypeEnvironment = _currentTypeEnvironment;
    _currentTypeEnvironment =
        ClassTypeEnvironment(node.enclosingClass.typeParameters);

    var params = <js_ast.Parameter>[];
    // Generic class constructors accept their RTI as their first argument.
    params.addAll(_emitParameters(node.function));
    var body = _withCurrentFunction(
        node.function,
        () => _superDisallowed(
            () => _emitConstructorBody(node, fields, className)));

    var end = _nodeEnd(node.fileEndOffset);
    _currentUri = savedUri;
    _staticTypeContext.leaveMember(node);
    end ??= _nodeEnd(node.enclosingClass.fileEndOffset);

    var constructor = js_ast.Fun([
      if (_requiresRtiForInstantiation(node.enclosingClass)) _rtiParam,
      ...params
    ], js_ast.Block(body))
      ..sourceInformation = end;

    _currentTypeEnvironment = savedTypeEnvironment;
    return constructor;
  }

  List<js_ast.Statement> _emitConstructorBody(
    Constructor node,
    List<Field> fields,
    js_ast.Expression className,
  ) {
    var cls = node.enclosingClass;

    // Generate optional/named argument value assignment. These can not have
    // side effects, and may be used by the constructor's initializers, so it's
    // nice to do them first.
    // Also for const constructors we need to ensure default values are
    // available for use by top-level constant initializers.
    var fn = node.function;
    var body = _emitArgumentInitializers(fn, node.name.text);

    // Class instances with type arguments are bound to their RTI on creation.
    // This must be bound early, as instantiated fields may reference this RTI.
    if (_requiresRtiForInstantiation(cls)) {
      // Only set the rti if there isn't one already. This avoids superclasses
      // overwriting the value already set by a subclass.
      var rtiProperty = _propertyName(js_ast.FixedNames.rtiName);
      body.add(js.statement('this.# = this.# || # || #', [
        rtiProperty,
        rtiProperty,
        _rtiParam,
        _runtimeCall('getReifiedType(this)')
      ]));
    }

    // Redirecting constructors are not allowed to have conventional
    // initializers but can have variable declarations in the form of
    // initializers to support named arguments appearing anywhere in the
    // arguments list.
    if (node.initializers.any((i) => i is RedirectingInitializer)) {
      body.add(_emitRedirectingConstructor(node.initializers, className));
      return body;
    }

    // Generate field initializers.
    // These are expanded into each non-redirecting constructor.
    // In the future we may want to create an initializer function if we have
    // multiple constructors, but it needs to be balanced against readability.
    body.add(_initializeFields(fields, node));

    // If no superinitializer is provided, an implicit superinitializer of the
    // form `super()` is added at the end of the initializer list, unless the
    // enclosing class is class Object.
    var superCall = node.initializers.whereType<SuperInitializer>().firstOrNull;
    var jsSuper = _emitSuperConstructorCallIfNeeded(cls, className, superCall);
    if (jsSuper != null) {
      // TODO(50465) Fix incorrect assumption there should always be a super
      // initializer here.
      if (superCall != null) jsSuper.sourceInformation = _nodeStart(superCall);
      body.add(jsSuper);
    }

    body.add(_emitFunctionScopedBody(fn));
    return body;
  }

  /// Returns the "actual" superclass of [c].
  ///
  /// Walks up the superclass chain looking for the first actual class
  /// skipping any synthetic classes inserted by the CFE.
  Class _superClassAsWritten(Class c) {
    var superclass = c.superclass!;
    while (superclass.isAnonymousMixin) {
      superclass = superclass.superclass!;
    }
    return superclass;
  }

  /// Returns `true` if [cls] requires/accepts an RTI during instantiation.
  ///
  /// We check [cls]'s transitive super classes for generic type parameters,
  /// but we do not consider anonymous mixins, implemented types or mixin on
  /// clauses - as their constructors are never invoked via super calls.
  /// Synthetic mixins are also skipped (despite sometimes having type
  /// parameters) since they can't be referenced during instantiation.
  ///
  /// Context: type arguments must be provided to a generic class during its
  /// instantiation. To avoid extraneous RTI evals, we pass the entire class's
  /// RTI instead of each type parameter's RTI individually. RTIs are attached
  /// to the instance on the hidden '$ti' field (see: FixedNames.rtiName). We
  /// attach RTIs eagerly (i.e., closer to the 'leaf' than the 'root') for
  /// simplicity. Setters on 'this' propagate up super calls since Dart super
  /// calls are synthetic. Ordinary JS super calls would require us to
  /// propagate the RTI all the way to the 'uppermost' generic class.
  bool _requiresRtiForInstantiation(Class? cls) {
    if (cls == null) return false;
    var cachedResult = _requiresRtiForInstantiationCache[cls];
    if (cachedResult != null) return cachedResult;
    // Skip synthetic mixins since their RTIs are never needed during
    // instantiation.
    if (cls.isAnonymousMixin) {
      cls = _superClassAsWritten(cls);
    }
    var hasTypeParameters = cls.typeParameters.isNotEmpty ||
        _requiresRtiForInstantiation(cls.superclass);
    _requiresRtiForInstantiationCache[cls] = hasTypeParameters;
    return hasTypeParameters;
  }

  js_ast.LiteralString _constructorName(String name) {
    if (name == '') {
      // Default constructors (factory or not) use `new` as their name.
      return _propertyName('new');
    }
    return _emitStaticMemberName(name);
  }

  js_ast.Statement _emitRedirectingConstructor(
      List<Initializer> initializers, js_ast.Expression className) {
    var jsInitializers = <js_ast.Statement>[];
    for (var init in initializers) {
      if (init is LocalInitializer) {
        // Temporary locals are created when named arguments don't appear at
        // the end of the arguments list.
        jsInitializers.add(visitVariableDeclaration(init.variable));
      } else if (init is RedirectingInitializer) {
        var rtiParam = _requiresRtiForInstantiation(init.target.enclosingClass)
            ? _rtiParam
            : null;
        // We can't dispatch to the constructor with `this.new` as that might
        // hit a derived class constructor with the same name.
        var initializer = js.statement('#.#.call(this, #);', [
          className,
          _constructorName(init.target.name.text),
          [
            if (rtiParam != null) rtiParam,
            ..._emitArgumentList(init.arguments, types: false)
          ]
        ]);
        jsInitializers.add(initializer);
      }
    }
    return js_ast.Block(jsInitializers);
  }

  js_ast.Statement? _emitSuperConstructorCallIfNeeded(
      Class c, js_ast.Expression className, SuperInitializer? superInit) {
    if (c == _coreTypes.objectClass) return null;

    Constructor ctor;
    List<js_ast.Expression> args;
    if (superInit == null) {
      ctor = unnamedConstructor(c.superclass!)!;
      args = [];
    } else {
      ctor = superInit.target;
      var savedTypeEnvironment = _currentTypeEnvironment;
      _currentTypeEnvironment = ClassTypeEnvironment(c.typeParameters);
      // An RTI will already have been set at the constructor call site, so
      // pass nothing if the superclass is expecting an RTI.
      var rti = _requiresRtiForInstantiation(ctor.enclosingClass)
          ? js_ast.LiteralNull()
          : null;
      args = [
        if (rti != null) rti,
        ..._emitArgumentList(superInit.arguments, types: true)
      ];

      _currentTypeEnvironment = savedTypeEnvironment;
    }
    // We can skip the super call if it's empty. Most commonly this happens for
    // things that extend Object, and don't have any field initializers or their
    // own default constructor.
    if (ctor.name.text == '' && !_hasUnnamedSuperConstructor(c)) {
      return null;
    }
    return _emitSuperConstructorCall(ctor, className, ctor.name.text, args);
  }

  js_ast.Statement _emitSuperConstructorCall(Constructor constructor,
      js_ast.Expression className, String name, List<js_ast.Expression> args) {
    return js.statement('#.#.call(this, #);', [
      _emitJSObjectGetPrototypeOf(className, fullyQualifiedName: true),
      _constructorName(name),
      args
    ]);
  }

  bool _hasUnnamedInheritedConstructor(Class? c) {
    if (c == null) return false;
    return _hasUnnamedConstructor(c) || _hasUnnamedSuperConstructor(c);
  }

  bool _hasUnnamedSuperConstructor(Class c) {
    return _hasUnnamedConstructor(c.mixedInClass) ||
        _hasUnnamedInheritedConstructor(c.superclass);
  }

  bool _hasUnnamedConstructor(Class? c) {
    if (c == null || c == _coreTypes.objectClass) return false;
    var ctor = unnamedConstructor(c);
    if (ctor != null && !ctor.isSynthetic) return true;
    return c.fields.any((f) => !f.isStatic);
  }

  /// Initialize fields. They follow the sequence:
  ///
  ///   1. field declaration initializer if non-const,
  ///   2. field initializing parameters,
  ///   3. constructor field initializers,
  ///   4. initialize fields not covered in 1-3
  js_ast.Statement _initializeFields(List<Field> fields, [Constructor? ctor]) {
    // Run field initializers if they can have side-effects.
    var ctorFields = ctor?.initializers
        .whereType<FieldInitializer>()
        .map((c) => c.field)
        .toSet();

    var body = <js_ast.Statement>[];
    void emitFieldInit(Field f, Expression? initializer, TreeNode hoverInfo) {
      var virtualField = _classProperties!.virtualFields[f];

      // Avoid calling getSymbol on _declareMemberName since _declareMemberName
      // calls _emitMemberName downstream, which already invokes getSymbol.
      var access = virtualField == null
          ? _declareMemberName(f)
          : _getSymbol(virtualField);
      var jsInit = _visitInitializer(initializer, f.annotations);
      body.add(jsInit
          .toAssignExpression(js.call('this.#', [access])
            ..sourceInformation = _nodeStart(hoverInfo))
          .toStatement());
    }

    for (var f in fields) {
      if (f.isStatic) continue;
      var init = f.initializer;
      if (ctorFields != null &&
          ctorFields.contains(f) &&
          (init == null || _constants.isConstant(init))) {
        continue;
      }
      _staticTypeContext.enterMember(f);
      emitFieldInit(f, init, f);
      _staticTypeContext.leaveMember(f);
    }

    // Run constructor field initializers such as `: foo = bar.baz`
    if (ctor != null) {
      for (var init in ctor.initializers) {
        if (init is FieldInitializer) {
          emitFieldInit(init.field, init.value, init);
        } else if (init is LocalInitializer) {
          body.add(visitVariableDeclaration(init.variable));
        } else if (init is AssertInitializer) {
          body.add(visitAssertStatement(init.statement));
        }
      }
    }

    return js_ast.Statement.from(body);
  }

  js_ast.Expression _visitInitializer(
      Expression? init, List<Expression> annotations) {
    // explicitly initialize to null, to avoid getting `undefined`.
    // TODO(jmesserly): do this only for vars that aren't definitely assigned.
    if (init == null) return js_ast.LiteralNull();
    return _annotatedNullCheck(annotations)
        ? _notNull(init)
        : _visitExpression(init);
  }

  js_ast.Expression _notNull(Expression expr) {
    var jsExpr = _visitExpression(expr);
    if (!_isNullable(expr)) return jsExpr;
    return _runtimeCall('notNull(#)', [jsExpr]);
  }

  /// If the class has only factory constructors, and it can be mixed in,
  /// then we need to emit a special hidden default constructor for use by
  /// mixins.
  bool _usesMixinNew(Class mixin) {
    // TODO(jmesserly): mixin declarations don't get implicit constructor nodes,
    // even if they have fields, so we need to ensure they're getting generated.
    return mixin.isMixinDeclaration && _hasUnnamedConstructor(mixin) ||
        mixin.superclass?.superclass == null &&
            mixin.constructors.every((c) => c.isExternal);
  }

  js_ast.Statement _addConstructorToClass(Class c, js_ast.Expression className,
      js_ast.LiteralString name, js_ast.Expression jsCtor) {
    jsCtor = _defineValueOnClass(c, className, name, jsCtor);
    return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
  }

  /// Whether any superclass of [c] defines a static [name].
  bool _superclassHasStatic(Class c, String memberName) {
    // Note: because we're only considering statics, we can ignore mixins.
    // We're only trying to find conflicts due to JS inheriting statics.
    var superclass = c.superclass;
    var name = Name(memberName, c.enclosingLibrary);
    while (true) {
      if (superclass == null) return false;
      for (var m in superclass.members) {
        if (m.name == name &&
            (m is Procedure && m.isStatic || m is Field && m.isStatic)) {
          return true;
        }
      }
      superclass = superclass.superclass;
    }
  }

  List<js_ast.Method> _emitClassMethods(Class c) {
    var virtualFields = _classProperties!.virtualFields;

    var jsMethods = <js_ast.Method?>[];
    var hasJsPeer = _extensionTypes.isNativeClass(c);
    var hasIterator = false;

    if (c == _coreTypes.objectClass) {
      // Dart does not use ES6 constructors.
      // Add an error to catch any invalid usage.
      jsMethods.add(js_ast.Method(
          _propertyName('constructor'),
          js.fun(r'''function() {
                throw Error("use `new " + # +
                    ".new(...)` to create a Dart object");
              }''', [
            _runtimeCall('typeName(#)', [_runtimeCall('getReifiedType(this)')])
          ])));
    } else if (c == _jsArrayClass) {
      // Provide access to the Array constructor property, so it works like
      // other native types (rather than calling the Dart Object "constructor"
      // above, which throws).
      //
      // This will become obsolete when
      // https://github.com/dart-lang/sdk/issues/31003 is addressed.
      jsMethods.add(js_ast.Method(
          _propertyName('constructor'), js.fun(r'function() { return []; }')));
    }

    var staticFieldNames = <Name>{};
    for (var m in c.fields) {
      if (m.isStatic) {
        staticFieldNames.add(m.name);
      } else if (_extensionTypes.isNativeClass(c)) {
        jsMethods.addAll(_emitNativeFieldAccessors(m));
      } else if (virtualFields.containsKey(m)) {
        jsMethods.addAll(_emitVirtualFieldAccessor(m));
      }
    }

    var getters = <String, Procedure>{};
    var setters = <String, Procedure>{};
    for (var m in c.procedures) {
      if (m.isAbstract) continue;
      if (m.isGetter) {
        getters[m.name.text] = m;
      } else if (m.isSetter) {
        setters[m.name.text] = m;
      }
    }

    var savedUri = _currentUri;
    for (var m in c.procedures) {
      // Static accessors on static/lazy fields are emitted earlier in
      // `_emitStaticFieldsAndAccessors`.
      if (m.isStatic && m.isAccessor && staticFieldNames.contains(m.name)) {
        continue;
      }
      _staticTypeContext.enterMember(m);
      // For the Dart SDK, we use the member URI because it may be different
      // from the class (because of patch files). User code does not need this.
      //
      // TODO(jmesserly): CFE has a bug(?) where nSM forwarders sometimes have a
      // bogus file URI, that is mismatched compared to the offsets. This causes
      // a crash when we look up the location. So for those forwarders, we just
      // suppress source spans.
      _currentUri = m.isNoSuchMethodForwarder ? null : m.fileUri;
      if (_isForwardingStub(m)) {
        // TODO(jmesserly): is there any other kind of forwarding stub?
        jsMethods.addAll(_emitCovarianceCheckStub(m));
      } else if (m.isFactory) {
        if (m.isRedirectingFactory) {
          // Skip redirecting factories (they've already been resolved).
        } else {
          jsMethods.add(_emitFactoryConstructor(m));
        }
      } else if (m.isAccessor) {
        jsMethods.add(_emitMethodDeclaration(m));
        jsMethods.add(_emitSuperAccessorWrapper(m, getters, setters));
        if (!hasJsPeer && m.isGetter && m.name.text == 'iterator') {
          hasIterator = true;
          jsMethods.add(_emitIterable(c));
        }
      } else {
        jsMethods.add(_emitMethodDeclaration(m));
      }
      _staticTypeContext.leaveMember(m);
    }
    _currentUri = savedUri;

    // If the type doesn't have an `iterator`, but claims to implement Iterable,
    // we inject the adaptor method here, as it's less code size to put the
    // helper on a parent class. This pattern is common in the core libraries
    // (e.g. IterableMixin<E> and IterableBase<E>).
    //
    // (We could do this same optimization for any interface with an `iterator`
    // method, but that's more expensive to check for, so it doesn't seem worth
    // it. The above case for an explicit `iterator` method will catch those.)
    if (!hasJsPeer && !hasIterator) {
      jsMethods.add(_emitIterable(c));
    }

    // Add all of the super helper methods
    jsMethods.addAll(_superHelpers.values);

    return jsMethods.nonNulls.toList();
  }

  bool _isForwardingStub(Procedure member) {
    if (member.isForwardingStub || member.isForwardingSemiStub) {
      if (!_currentLibrary!.importUri.isScheme('dart')) return true;
      // TODO(jmesserly): external methods in the SDK seem to get incorrectly
      // tagged as forwarding stubs even if they are patched. Perhaps there is
      // an ordering issue in CFE. So for now we pattern match to see if it
      // looks like an actual forwarding stub.
      //
      // We may be able to work around this in a cleaner way by simply emitting
      // the code, and letting the normal covariance check logic handle things.
      // But currently we use _emitCovarianceCheckStub to work around some
      // issues in the stubs.
      var body = member.function.body;
      if (body is ReturnStatement) {
        var expr = body.expression;
        return expr is SuperMethodInvocation || expr is SuperPropertySet;
      }
    }
    return false;
  }

  /// Emits a method, getter, or setter.
  js_ast.Method? _emitMethodDeclaration(Procedure member) {
    if (member.isAbstract) {
      return null;
    }

    js_ast.Fun fn;
    if (member.isExternal && !member.isNoSuchMethodForwarder) {
      if (member.isStatic) {
        // TODO(vsm): Do we need to handle this case?
        return null;
      }
      fn = _emitNativeFunctionBody(member);
    } else {
      fn = _withMethodDeclarationContext(
          member,
          () => _emitFunction(member.function, member.name.text,
              functionBody: _toSourceLocation(member.fileOffset),
              functionEnd: _toSourceLocation(member.fileEndOffset)));
    }

    var method = js_ast.Method(_declareMemberName(member), fn,
        isGetter: member.isGetter,
        isSetter: member.isSetter,
        isStatic: member.isStatic);

    if (isTearOffLowering(member)) {
      // Remove all source information from static methods introduced by the
      // constructor tearoff CFE lowering.
      method.accept(js_ast.SourceInformationClearer());
    } else {
      method.sourceInformation = _nodeEnd(member.fileEndOffset);
    }

    return method;
  }

  js_ast.Fun _emitNativeFunctionBody(Procedure node) {
    var name = _annotationName(node, isJSAnnotation) ?? node.name.text;
    if (node.isGetter) {
      var returnValue = js('this.#', [name]);
      if (_isNullCheckableNative(node)) {
        // Add a potential null-check on native getter if type is non-nullable.
        returnValue = _runtimeCall('checkNativeNonNull(#)', [returnValue]);
      }
      return js_ast.Fun([], js.block('{ return #; }', [returnValue]));
    } else if (node.isSetter) {
      var params = _emitParameters(node.function);
      return js_ast.Fun(
          params, js.block('{ this.# = #; }', [name, params.last]));
    } else {
      var returnValue = js('this.#.apply(this, args)', [name]);
      if (_isNullCheckableNative(node)) {
        // Add a potential null-check on return value if type is non-nullable.
        returnValue = _runtimeCall('checkNativeNonNull(#)', [returnValue]);
      }
      return js.fun('function (...args) { return #; }', [returnValue]);
    }
  }

  List<js_ast.Method> _emitCovarianceCheckStub(Procedure member) {
    // TODO(jmesserly): kernel stubs have a few problems:
    // - they're generated even when there is no concrete super member
    // - the stub parameter types don't match the types we need to check to
    //   ensure soundness of the super member, so we must lookup the super
    //   member and determine checks ourselves.
    // - it generates getter stubs, but these are not used
    if (member.isGetter) return const [];

    var enclosingClass = member.enclosingClass;
    var superMember = member.concreteForwardingStubTarget ??
        member.abstractForwardingStubTarget;

    if (superMember == null) return const [];

    DartType substituteType(DartType t) {
      return _typeFromClass(t, superMember.enclosingClass!, enclosingClass!);
    }

    var superMemberFunction = superMember.function;
    var name = _declareMemberName(member);
    if (member.isSetter) {
      if (superMember is Field && isCovariantField(superMember) ||
          superMember is Procedure &&
              isCovariantParameter(
                  superMemberFunction!.positionalParameters[0])) {
        return const [];
      }
      var setterType =
          substituteType(superMember.superSetterType).extensionTypeErasure;
      if (_types.isTop(setterType)) return const [];
      return [
        js_ast.Method(
            name,
            js.fun('function(x) { return super.# = #; }',
                [name, _emitCast(_emitIdentifier('x'), setterType)]),
            isSetter: true),
        js_ast.Method(name, js.fun('function() { return super.#; }', [name]),
            isGetter: true)
      ];
    }
    assert(!member.isAccessor);

    var superMethodType = substituteType(superMemberFunction!
            .computeThisFunctionType(superMember.enclosingLibrary.nonNullable))
        as FunctionType;
    var function = member.function;

    var body = <js_ast.Statement>[];
    var typeParameters = superMethodType.typeParameters;
    _emitCovarianceBoundsCheck(typeParameters, body);

    var typeFormals = _emitTypeFormals(typeParameters);
    var jsParams = List<js_ast.Parameter>.from(typeFormals);
    var positionalParameters = function.positionalParameters;
    for (var i = 0, n = positionalParameters.length; i < n; i++) {
      var param = positionalParameters[i];
      var jsParam = _emitIdentifier(param.name!);
      jsParams.add(jsParam);

      if (isCovariantParameter(param) &&
          !isCovariantParameter(superMemberFunction.positionalParameters[i])) {
        var check = _emitCast(jsParam, superMethodType.positionalParameters[i]);
        if (i >= function.requiredParameterCount) {
          body.add(js.statement('if (# !== void 0) #;', [jsParam, check]));
        } else {
          body.add(check.toStatement());
        }
      }
    }
    var namedParameters = function.namedParameters;
    for (var param in namedParameters) {
      if (isCovariantParameter(param) &&
          !isCovariantParameter(superMemberFunction.namedParameters
              .firstWhere((n) => n.name == param.name))) {
        var name = _propertyName(param.name!);
        var paramType = superMethodType.namedParameters
            .firstWhere((n) => n.name == param.name);
        body.add(js.statement('if (#) #;', [
          _namedArgumentProbe(name),
          _emitCast(
              js_ast.PropertyAccess(_namedArgumentTemp, name), paramType.type)
        ]));
      }
    }

    if (body.isEmpty) return const []; // No checks were needed.

    if (namedParameters.isNotEmpty) jsParams.add(_namedArgumentTemp);
    body.add(js.statement('return super.#(#);', [name, jsParams]));
    return [js_ast.Method(name, js_ast.Fun(jsParams, js_ast.Block(body)))];
  }

  /// Emits a Dart factory constructor to a JS static method.
  js_ast.Method? _emitFactoryConstructor(Procedure node) {
    if (node.isExternal || isUnsupportedFactoryConstructor(node)) return null;
    var function = node.function;

    /// Note: factory constructors can't use `sync*`/`async*`/`async` bodies
    /// because it would return the wrong type, so we can assume `sync` here.
    ///
    /// We can also skip the logic in [_emitFunction] related to operator
    /// methods like ==, as well as generic method parameters.
    ///
    /// If a future Dart version allows factory constructors to take their
    /// own type parameters, this will need to be changed to call
    /// [_emitFunction] instead.
    var name = node.name.text;
    var savedTypeEnvironment = _currentTypeEnvironment;
    _currentTypeEnvironment = RtiTypeEnvironment([
      ...function.typeParameters,
      ..._currentTypeEnvironment.classTypeParameters
    ]);
    var jsBody = js_ast.Block(_withCurrentFunction(function, () {
      var block = _emitArgumentInitializers(function, name);
      block.add(_emitFunctionScopedBody(function));
      return block;
    }));
    var jsName = _constructorName(name);
    memberNames[node] = jsName.valueWithoutQuotes;

    // Generic class constructors accept their RTI as their first argument.
    var method = js_ast.Method(
      jsName,
      js_ast.Fun(
        [
          if (_requiresRtiForInstantiation(node.enclosingClass)) _rtiParam,
          ..._emitParameters(function)
        ],
        jsBody,
      ),
      isStatic: true,
    )..sourceInformation = _nodeEnd(node.fileEndOffset);
    _currentTypeEnvironment = savedTypeEnvironment;
    return method;
  }

  /// Emits the expression necessary to access a constructor of [type];
  js_ast.Expression _emitConstructorAccess(InterfaceType type) =>
      _emitJSInterop(type.classNode) ?? _emitClassRef(type);

  /// This is called whenever a derived class needs to introduce a new field,
  /// shadowing a field or getter/setter pair on its parent.
  ///
  /// This is important because otherwise, trying to read or write the field
  /// would end up calling the getter or setter, and one of those might not even
  /// exist, resulting in a runtime error. Even if they did exist, that's the
  /// wrong behavior if a new field was declared.
  List<js_ast.Method> _emitVirtualFieldAccessor(Field field) {
    var virtualField = _classProperties!.virtualFields[field]!;
    var virtualFieldSymbol = _getSymbol(virtualField);
    var name = _declareMemberName(field);

    var getter = js.fun('function() { return this[#]; }', [virtualFieldSymbol]);
    var jsGetter = js_ast.Method(name, getter, isGetter: true)
      ..sourceInformation = _nodeStart(field);

    var body = <js_ast.Statement>[];
    var value = _emitIdentifier('value');
    // Avoid adding a null checks on forwarding field setters.
    if (field.hasSetter &&
        _requiresExtraNullCheck(field.setterType, field.annotations)) {
      body.add(
          _nullSafetyParameterCheck(value, field.location, field.name.text));
    }
    var args = field.isFinal
        ? [js_ast.Super(), name, value]
        : [
            js_ast.This(),
            virtualFieldSymbol,
            if (isCovariantField(field)) _emitCast(value, field.type) else value
          ];
    body.add(js.call('#[#] = #', args).toStatement());
    var jsSetter = js_ast.Method(name, js_ast.Fun([value], js_ast.Block(body)),
        isSetter: true)
      ..sourceInformation = _nodeStart(field);

    return [jsGetter, jsSetter];
  }

  /// Provide Dart getters and setters that forward to the underlying native
  /// field.  Note that the Dart names are always symbolized to avoid
  /// conflicts.  They will be installed as extension methods on the underlying
  /// native type.
  List<js_ast.Method> _emitNativeFieldAccessors(Field field) {
    // TODO(vsm): Can this by meta-programmed?
    // E.g., dart.nativeField(symbol, jsName)
    // Alternatively, perhaps it could be meta-programmed directly in
    // dart.registerExtensions?
    var jsMethods = <js_ast.Method>[];
    assert(!field.isStatic);

    var name = _annotationName(field, isJSName) ?? field.name.text;
    // Generate getter
    var fn = js_ast.Fun([], js.block('{ return this.#; }', [name]));
    var method = js_ast.Method(_declareMemberName(field), fn, isGetter: true);
    jsMethods.add(method);

    // Generate setter
    if (!field.isFinal) {
      var value = _emitScopedId('value');
      fn = js_ast.Fun([value], js.block('{ this.# = #; }', [name, value]));
      method = js_ast.Method(_declareMemberName(field), fn, isSetter: true);
      jsMethods.add(method);
    }

    return jsMethods;
  }

  /// Emit a getter (or setter) that simply forwards to the superclass getter
  /// (or setter).
  ///
  /// This is needed because in ES6, if you only override a getter
  /// (alternatively, a setter), then there is an implicit override of the
  /// setter (alternatively, the getter) that does nothing.
  js_ast.Method? _emitSuperAccessorWrapper(Procedure member,
      Map<String, Procedure> getters, Map<String, Procedure> setters) {
    if (member.isAbstract) return null;

    var name = member.name.text;
    var memberName = _declareMemberName(member);
    if (member.isGetter) {
      if (!setters.containsKey(name) &&
          _classProperties!.inheritedSetters.contains(name)) {
        // Generate a setter that forwards to super.
        var fn = js.fun('function(value) { super[#] = value; }', [memberName]);
        return js_ast.Method(memberName, fn, isSetter: true);
      }
    } else {
      assert(member.isSetter);
      if (!getters.containsKey(name) &&
          _classProperties!.inheritedGetters.contains(name)) {
        // Generate a getter that forwards to super.
        var fn = js.fun('function() { return super[#]; }', [memberName]);
        return js_ast.Method(memberName, fn, isGetter: true);
      }
    }
    return null;
  }

  /// Support for adapting dart:core Iterable to ES6 versions.
  ///
  /// This lets them use for-of loops transparently:
  /// <https://github.com/lukehoban/es6features#iterators--forof>
  ///
  /// This will return `null` if the adapter was already added on a super type,
  /// otherwise it returns the adapter code.
  // TODO(jmesserly): should we adapt `Iterator` too?
  js_ast.Method? _emitIterable(Class c) {
    var iterable = _hierarchy.getClassAsInstanceOf(c, _coreTypes.iterableClass);
    if (iterable == null) return null;
    var superclass = c.superclass!;
    // If a parent had an `iterator` (concrete or abstract) or implements
    // Iterable, we know the adapter is already there, so we can skip it as a
    // simple code size optimization.
    var parent = _hierarchy.getDispatchTarget(superclass, Name('iterator'));
    if (parent != null) return null;

    var parentIterable =
        _hierarchy.getClassAsInstanceOf(superclass, _coreTypes.iterableClass);
    if (parentIterable != null) return null;

    if (c.enclosingLibrary.importUri.isScheme('dart') &&
        c.procedures.any((m) => _jsExportName(m) == 'Symbol.iterator')) {
      return null;
    }

    // Otherwise, emit the adapter method, which wraps the Dart iterator in
    // an ES6 iterator.
    return js_ast.Method(
        js.call('Symbol.iterator'),
        // TODO(nshahan) Don't access values in `runtimeModule` outside of
        // `runtimeCall`.
        js.call('function() { return new #.JsIterator(this.#); }', [
          _runtimeModule,
          _emitMemberName('iterator', memberClass: _coreTypes.iterableClass)
        ]) as js_ast.Fun);
  }

  void _registerExtensionType(
      Class c, String jsPeerName, List<js_ast.Statement> body) {
    var className = _emitTopLevelName(c);
    if (_typeRep.isPrimitive(_coreTypes.nonNullableRawType(c))) {
      body.add(_runtimeStatement(
          'definePrimitiveHashCode(#.prototype)', [className]));
    }
    body.add(_runtimeStatement(
        'registerExtension(#, #)', [js.string(jsPeerName), className]));
  }

  void _emitTopLevelFields(List<Field> fields) {
    if (_isSdkInternalRuntime(_currentLibrary!)) {
      /// Treat dart:_runtime fields as safe to eagerly evaluate.
      // TODO(jmesserly): it'd be nice to avoid this special case.
      var lazyFields = <Field>[];
      var savedUri = _currentUri;

      // Helper functions to test if a constructor invocation is internal and
      // should be eagerly evaluated.
      bool isInternalConstructor(ConstructorInvocation node) {
        var type = node.getStaticType(_staticTypeContext) as InterfaceType;
        var library = type.classNode.enclosingLibrary;
        return _isSdkInternalRuntime(library);
      }

      for (var field in fields) {
        _staticTypeContext.enterMember(field);
        var init = field.initializer;
        if (init == null ||
            init is BasicLiteral ||
            init is ConstructorInvocation && isInternalConstructor(init) ||
            init is StaticInvocation && isInlineJS(init.target)) {
          if (init is ConstructorInvocation) {
            // This is an eagerly executed constructor invocation.  We need to
            // ensure the class is emitted before this statement.
            var type = init.getStaticType(_staticTypeContext) as InterfaceType;
            _emitClass(type.classNode);
          }
          _currentUri = field.fileUri;
          _moduleItems.add(js.statement('# = #;', [
            _emitTopLevelName(field),
            _visitInitializer(init, field.annotations)
          ]));
        } else {
          lazyFields.add(field);
        }
        _staticTypeContext.leaveMember(field);
      }

      _currentUri = savedUri;
      fields = lazyFields;
    }

    if (fields.isEmpty) return;
    _moduleItems.add(_emitLazyMembers(
        _emitLibraryName(_currentLibrary!), fields, _emitTopLevelMemberName));
  }

  js_ast.Statement _emitLazyMembers(
    js_ast.Expression objExpr,
    Iterable<Member> members,
    js_ast.LiteralString Function(Member) emitMemberName,
  ) {
    var accessors = <js_ast.Method>[];
    var savedUri = _currentUri;

    for (var member in members) {
      _currentUri = member.fileUri;
      _staticTypeContext.enterMember(member);
      var access = emitMemberName(member);
      memberNames[member] = access.valueWithoutQuotes;

      if (member is Field) {
        accessors.add(js_ast.Method(access, _emitStaticFieldInitializer(member),
            isGetter: true)
          ..sourceInformation = _hoverComment(
              js_ast.PropertyAccess(objExpr, access),
              member.fileOffset,
              member.name.text.length));
        if (!member.isFinal && !member.isConst) {
          var body = <js_ast.Statement>[];
          var value = _emitIdentifier('value');
          if (_requiresExtraNullCheck(member.setterType, member.annotations)) {
            body.add(_nullSafetyParameterCheck(
                value, member.location, member.name.text));
          }
          // Even when no null check is present a dummy setter is still required
          // to indicate writeable.
          accessors.add(js_ast.Method(
              access, js_ast.Fun([value], js_ast.Block(body)),
              isSetter: true));
        }
      } else if (member is Procedure) {
        accessors.add(js_ast.Method(
            access, _emitFunction(member.function, member.name.text),
            isGetter: member.isGetter, isSetter: member.isSetter)
          ..sourceInformation = _hoverComment(
              js_ast.PropertyAccess(objExpr, access),
              member.fileOffset,
              member.name.text.length));
      } else {
        throw UnsupportedError(
            'Unsupported lazy member type ${member.runtimeType}: $member');
      }
      _staticTypeContext.leaveMember(member);
    }
    _currentUri = savedUri;

    return _runtimeStatement('defineLazy(#, { # })', [objExpr, accessors]);
  }

  js_ast.Fun _emitStaticFieldInitializer(Field field) {
    return js_ast.Fun([], js_ast.Block(_withLetScope(() {
      return [
        js_ast.Return(_visitInitializer(field.initializer, field.annotations))
      ];
    })));
  }

  List<js_ast.Statement> _withLetScope(
      List<js_ast.Statement> Function() visitBody) {
    var savedLetVariables = _letVariables;
    _letVariables = [];

    var body = visitBody();
    var letVars = _initLetVariables();
    if (letVars != null) body.insert(0, letVars);

    _letVariables = savedLetVariables;
    return body;
  }

  js_ast.PropertyAccess _emitTopLevelName(NamedNode n, {String suffix = ''}) {
    return _emitJSInterop(n) ??
        _emitTopLevelNameNoExternalInterop(n, suffix: suffix);
  }

  /// Like [_emitMemberName], but for declaration sites.
  ///
  /// Unlike call sites, we always have an element available, so we can use it
  /// directly rather than computing the relevant options for [_emitMemberName].
  js_ast.Expression _declareMemberName(Member m, {bool? useExtension}) {
    var c = m.enclosingClass;
    return _emitMemberName(m.name.text,
        isStatic: m is Field ? m.isStatic : (m as Procedure).isStatic,
        useExtension:
            useExtension ?? c != null && _extensionTypes.isNativeClass(c),
        member: m);
  }

  /// This handles member renaming for private names and operators.
  ///
  /// Private names are generated using ES6 symbols:
  ///
  ///     // At the top of the module:
  ///     let _x = Symbol('_x');
  ///     let _y = Symbol('_y');
  ///     ...
  ///
  ///     class Point {
  ///       Point(x, y) {
  ///         this[_x] = x;
  ///         this[_y] = y;
  ///       }
  ///       get x() { return this[_x]; }
  ///       get y() { return this[_y]; }
  ///     }
  ///
  /// For user-defined operators the following names are allowed:
  ///
  ///     <, >, <=, >=, ==, -, +, /, ~/, *, %, |, ^, &, <<, >>, >>>, []=, [], ~
  ///
  /// They generate code like:
  ///
  ///     x['+'](y)
  ///
  /// There are three exceptions: [], []= and unary -.
  /// The indexing operators we use `get` and `set` instead:
  ///
  ///     x.get('hi')
  ///     x.set('hi', 123)
  ///
  /// This follows the same pattern as ECMAScript 6 Map:
  /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map>
  ///
  /// Unary minus looks like: `x._negate()`.
  ///
  /// Equality is a bit special, it is generated via the Dart `equals` runtime
  /// helper, that checks for null. The user defined method is called '=='.
  ///
  js_ast.Expression _emitMemberName(String name,
      {bool isStatic = false,
      bool? useExtension,
      Member? member,
      Class? memberClass}) {
    // Static members skip the rename steps and may require JS interop renames.
    if (isStatic) {
      var memberName = _emitStaticMemberName(name, member);
      if (member != null && !isTearOffLowering(member)) {
        // No need to track the names of methods that were created by the CFE
        // lowering and don't exist in the original source code.
        memberNames[member] = memberName.valueWithoutQuotes;
      }
      return memberName;
    }

    // We allow some (illegal in Dart) member names to be used in our private
    // SDK code. These renames need to be included at every declaration,
    // including overrides in subclasses.
    if (member != null) {
      var runtimeName = _jsExportName(member);
      if (runtimeName != null) {
        var parts = runtimeName.split('.');
        // TODO(nshahan) Record the name for this member in memberNames.
        if (parts.length < 2) return _propertyName(runtimeName);

        js_ast.Expression result = _emitIdentifier(parts[0]);
        for (var i = 1; i < parts.length; i++) {
          result = js_ast.PropertyAccess(result, _propertyName(parts[i]));
        }
        // TODO(nshahan) Record the name for this member in memberNames.
        return result;
      }
    }

    memberClass ??= member?.enclosingClass;
    if (name.startsWith('_')) {
      // Use the library that this private member's name is scoped to.
      var memberLibrary = member?.name.library ??
          memberClass?.enclosingLibrary ??
          _currentLibrary!;
      if (member != null) {
        // TODO(40273) Move this name collection to another location.
        // We really only want to collect member names when the member is created,
        // not called.
        // Wrap the name as a symbol here so it matches what you would find at
        // runtime when you get all properties and symbols from an instance.
        memberNames[member] = 'Symbol($name)';
      }
      return _getSymbol(_emitPrivateNameSymbol(memberLibrary, name));
    }

    useExtension ??= _isSymbolizedMember(memberClass, name);
    name = js_ast.memberNameForDartMember(name, _isExternal(member));
    if (useExtension) {
      // TODO(nshahan) Record the name for this member in memberNames.
      return _getSymbol(_getExtensionSymbolInternal(name));
    }
    var memberName = _propertyName(name);
    if (member != null) {
      // TODO(40273) Move this name collection to another location.
      // We really only want to collect member names when the member is created,
      // not called.
      memberNames[member] = memberName.valueWithoutQuotes;
    }
    return memberName;
  }

  /// Don't symbolize native members that just forward to the underlying
  /// native member.  We limit this to non-renamed members as the receiver
  /// may be a mock type.
  ///
  /// Note, this is an underlying assumption here that, if another native type
  /// subtypes this one, it also forwards this member to its underlying native
  /// one without renaming.
  bool _isSymbolizedMember(Class? c, String name) {
    if (c == null) {
      return _isObjectMember(name);
    }
    c = _typeRep.getImplementationClass(_coreTypes.nonNullableRawType(c)) ?? c;
    if (_extensionTypes.isNativeClass(c)) {
      var member = _lookupForwardedMember(c, name);

      // Fields on a native class are implicitly native.
      // Methods/getters/setters are marked external/native.
      if (member is Field || _isExternal(member)) {
        // If the native member needs to be null-checked and we're running in
        // sound null-safety, we require symbolizing it in order to access the
        // null-check at the member definition.
        if (_isNullCheckableNative(member!)) return true;
        var jsName = _annotationName(member, isJSName);
        return jsName != null && jsName != name;
      } else {
        // Non-external members must be symbolized.
        return true;
      }
    }
    // If the receiver *may* be a native type (i.e., an interface allowed to
    // be implemented by a native class), conservatively symbolize - we don't
    // know whether it'll be implemented via forwarding.
    // TODO(vsm): Consider CHA here to be less conservative.
    return _extensionTypes.isNativeInterface(c);
  }

  final _forwardingCache = HashMap<Class, Map<String, Member?>>();

  Member? _lookupForwardedMember(Class c, String name) {
    // We only care about public methods.
    if (name.startsWith('_')) return null;

    var map = _forwardingCache.putIfAbsent(c, () => {});

    return map.putIfAbsent(
        name,
        () =>
            _hierarchy.getDispatchTarget(c, Name(name)) ??
            _hierarchy.getDispatchTarget(c, Name(name), setter: true));
  }

  js_ast.LiteralString _emitStaticMemberName(String name, [NamedNode? member]) {
    if (member != null) {
      var jsName = _emitJSInteropExternalStaticMemberName(member);
      if (jsName != null) return jsName;

      // Allow the Dart SDK to assign names to statics with the @JSExportName
      // annotation.
      var exportName = _jsExportName(member);
      if (exportName != null) return _propertyName(exportName);
    }
    if (member is Procedure && member.isFactory) {
      return _constructorName(member.name.text);
    }
    switch (name) {
      // Reserved for the compiler to do `x as T`.
      case 'as':
      // Reserved for the SDK to compute `Type.toString()`.
      case 'name':
      // Reserved by JS, not a valid static member name.
      case 'prototype':
        name += '_';
      default:
        // All trailing underscores static names are reserved for the compiler
        // or SDK libraries.
        //
        // If user code uses them, add an extra `_`.
        //
        // This also avoids collision with the renames above, e.g. `static as`
        // and `static as_` will become `as_` and `as__`.
        if (name.endsWith('_')) {
          name += '_';
        }
    }
    return _propertyName(name);
  }

  /// If [f] is a function passed to JS, make it throw at runtime when called if
  /// it isn't wrapped with `allowInterop`.
  ///
  /// Arguments which are _directly_ wrapped at the site they are passed are
  /// unmodified.
  Expression _assertInterop(Expression f) {
    // Erasing any extension types here for legacy JS interop support but if
    // using the new extension type interop the type system requires that
    // `.toJS` was called.
    var type = f.getStaticType(_staticTypeContext).extensionTypeErasure;
    if (type is FunctionType ||
        (type is InterfaceType && type.classNode == _coreTypes.functionClass)) {
      if (!isAllowInterop(f)) {
        return StaticInvocation(
            _assertInteropMethod, Arguments([f], types: [type]));
      }
    }
    return f;
  }

  /// Emit the name associated with external static members of interop classes.
  js_ast.LiteralString? _emitJSInteropExternalStaticMemberName(NamedNode n) {
    if (!usesJSInterop(n)) return null;
    if (n is Member && !n.isExternal) return null;
    var name = _annotationName(n, isJSInteropAnnotation) ?? getTopLevelName(n);
    assert(!name.contains('.'),
        'JS interop checker rejects dotted names on static class members');
    return js.escapedString(name, "'");
  }

  /// Emit the top-level name associated with [n], which should not be an
  /// external interop member.
  js_ast.PropertyAccess _emitTopLevelNameNoExternalInterop(NamedNode n,
      {String suffix = ''}) {
    // Some native tests use top-level native methods.
    var isTopLevelNative = n is Member && isNative(n);
    return js_ast.PropertyAccess(
        isTopLevelNative
            ? _runtimeCall('global.self')
            : _emitLibraryName(getLibrary(n)),
        _emitTopLevelMemberName(n, suffix: suffix));
  }

  /// Emits the member name portion of a top-level member.
  ///
  /// NOTE: usually you should use [_emitTopLevelName] instead of this. This
  /// function does not handle JS interop.
  js_ast.LiteralString _emitTopLevelMemberName(NamedNode n,
      {String suffix = ''}) {
    var name = _jsExportName(n) ?? getTopLevelName(n);
    return _propertyName(name + suffix);
  }

  bool _isExternal(Member? m) {
    // Corresponds to the names in memberNameForDartMember in
    // compiler/js_names.dart.
    const renamedJsMembers = ['prototype', 'constructor'];
    if (m is Procedure) {
      if (m.isExternal) return true;
      if (m.isNoSuchMethodForwarder) {
        if (renamedJsMembers.contains(m.name.text)) {
          return _hasExternalProcedure(m.enclosingClass!, m.name.text);
        }
      }
    }
    return false;
  }

  /// Returns true if anything up the class hierarchy externally defines a
  /// procedure with name = [name].
  ///
  /// Used to determine when we should alias Dart-JS reserved members
  /// (e.g., 'prototype' and 'constructor').
  bool _hasExternalProcedure(Class c, String name) {
    var classes = Queue<Class>()..add(c);

    while (classes.isNotEmpty) {
      var c = classes.removeFirst();
      var classesToCheck = [
        if (c.supertype != null) c.supertype!.classNode,
        for (var t in c.implementedTypes) t.classNode,
      ];
      classes.addAll(classesToCheck);
      for (var procedure in c.procedures) {
        if (procedure.name.text == name && !procedure.isNoSuchMethodForwarder) {
          return procedure.isExternal;
        }
      }
    }

    return false;
  }

  String? _jsNameWithoutGlobal(NamedNode n) {
    if (!usesJSInterop(n)) return null;
    var libraryJSName = _annotationName(getLibrary(n), isJSInteropAnnotation);
    var jsName =
        _annotationName(n, isJSInteropAnnotation) ?? getTopLevelName(n);
    return libraryJSName != null ? '$libraryJSName.$jsName' : jsName;
  }

  String? _emitJsNameWithoutGlobal(NamedNode n) {
    if (!usesJSInterop(n)) return null;
    _setEmitIfIncrementalLibrary(getLibrary(n));
    return _jsNameWithoutGlobal(n);
  }

  js_ast.PropertyAccess? _emitJSInterop(NamedNode n) {
    var jsName = _emitJsNameWithoutGlobal(n);
    if (jsName == null) return null;
    return _emitJSInteropForGlobal(jsName);
  }

  js_ast.PropertyAccess _emitJSInteropForGlobal(String name) {
    var parts = name.split('.');
    if (parts.isEmpty) parts = [''];
    js_ast.PropertyAccess? access;
    for (var part in parts) {
      access = js_ast.PropertyAccess(
          access ?? _runtimeCall('global'), js.escapedString(part, "'"));
    }
    return access!;
  }

  void _emitLibraryProcedures(Library library) {
    var procedures = library.procedures
        .where((p) =>
            !p.isExternal && !p.isAbstract && !_isStaticInteropTearOff(p))
        .toList();
    _moduleItems.addAll(procedures
        .where((p) => !p.isAccessor)
        .map(_emitLibraryFunction)
        .toList());
    _emitLibraryAccessors(procedures.where((p) => p.isAccessor).toList());
  }

  /// Check whether [p] is a tear-off for an external or synthetic static
  /// interop member.
  ///
  /// Users are disallowed from using these tear-offs, so we should avoid
  /// emitting them.
  bool _isStaticInteropTearOff(Procedure p) {
    final extensionMember = _extensionIndex.getExtensionMemberForTearOff(p);
    if (extensionMember != null && extensionMember.asProcedure.isExternal) {
      return true;
    }
    final extensionTypeMember =
        _extensionIndex.getExtensionTypeMemberForTearOff(p);
    if (extensionTypeMember != null &&
        extensionTypeMember.asProcedure.isExternal) {
      return true;
    }
    final enclosingClass = p.enclosingClass;
    if (enclosingClass != null && isStaticInteropType(enclosingClass)) {
      // @staticInterop types can't use generative constructors, so we only
      // check for tear-offs of factories. The one exception is a tear-off of a
      // default constructor, which is disallowed on @staticInterop classes.
      final factoryName = extractConstructorNameFromTearOff(p.name);
      if (factoryName != null) {
        if (factoryName.isEmpty &&
            enclosingClass.constructors.any((constructor) =>
                constructor.isSynthetic && constructor.name.text.isEmpty)) {
          return true;
        }
        if (enclosingClass.procedures.any((procedure) =>
            procedure.isFactory &&
            procedure.isExternal &&
            procedure.name.text == factoryName)) {
          return true;
        }
      }
    }
    return false;
  }

  void _emitLibraryAccessors(Iterable<Procedure> accessors) {
    if (accessors.isEmpty) return;
    _moduleItems.add(_runtimeStatement('copyProperties(#, { # })', [
      _emitLibraryName(_currentLibrary!),
      accessors.map(_emitLibraryAccessor).toList()
    ]));
  }

  js_ast.Method _emitLibraryAccessor(Procedure node) {
    var savedUri = _currentUri;
    _staticTypeContext.enterMember(node);
    _currentUri = node.fileUri;

    var name = node.name.text;
    memberNames[node] = name;
    var result = js_ast.Method(
        _propertyName(name), _emitFunction(node.function, name),
        isGetter: node.isGetter, isSetter: node.isSetter)
      ..sourceInformation = _nodeEnd(node.fileEndOffset);

    _currentUri = savedUri;
    _staticTypeContext.leaveMember(node);
    return result;
  }

  js_ast.Statement _emitLibraryFunction(Procedure p) {
    var savedUri = _currentUri;
    _staticTypeContext.enterMember(p);
    _currentUri = p.fileUri;

    var body = <js_ast.Statement>[];
    var fn = _emitFunction(p.function, p.name.text,
        functionBody: _toSourceLocation(p.fileOffset),
        functionEnd: _toSourceLocation(p.fileEndOffset))
      ..sourceInformation = _nodeEnd(p.fileEndOffset);

    if (_currentLibrary!.importUri.isScheme('dart') &&
        _isInlineJSFunction(p.function.body)) {
      fn = js_ast.simplifyPassThroughArrowFunCallBody(fn);
    }

    var nameExpr = _emitTopLevelName(p);
    var jsName = _safeFunctionNameForSafari(p.name.text, fn);
    var functionName = _emitScopedId(jsName);
    procedureIdentifiers[p] = functionName;
    body.add(js.statement(
        '# = #', [nameExpr, js_ast.NamedFunction(functionName, fn)]));

    _currentUri = savedUri;
    _staticTypeContext.leaveMember(p);

    if (_options.dynamicModule &&
        p.annotations.any((a) => _isEntrypointPragma(a, _coreTypes))) {
      if (_dynamicEntrypoint == null) {
        if (p.function.requiredParameterCount > 0) {
          // TODO(sigmund): this error should be caught by a kernel checker that
          // runs prior to DDC.
          throw StateError('Entrypoint ${p.name.text} must accept being called '
              'with 0 arguments.');
        } else {
          _dynamicEntrypoint = p;
        }
      } else {
        // TODO(sigmund): this error should be caught by a kernel checker that
        // runs prior to DDC.
        throw StateError('A module should define a single entrypoint.');
      }
    }

    return js_ast.Statement.from(body);
  }

  /// Choose a safe name for [fn].
  ///
  /// Most of the time we use [candidateName], except if the name collides
  /// with a parameter name and the function contains default parameter values.
  ///
  /// In ES6, functions containing default parameter values, which DDC
  /// generates when Dart uses positional optional parameters, cannot have
  /// two parameters with the same name. Because we have a similar restriction
  /// in Dart, this is not normally an issue we need to pay attention to.
  /// However, a bug in Safari makes it a syntax error to have the function
  /// name overlap with the parameter names as well. This rename works around
  /// such bug (dartbug.com/43520).
  static String _safeFunctionNameForSafari(
      String candidateName, js_ast.Fun fn) {
    if (fn.params.any((p) => p is js_ast.DestructuredVariable)) {
      while (fn.params.any((a) => a.parameterName == candidateName)) {
        candidateName = '$candidateName\$';
      }
    }
    return candidateName;
  }

  js_ast.Expression _emitFunctionTagged(js_ast.Expression fn, FunctionType type,
      {bool topLevel = false}) {
    var lazy = topLevel && !_canEmitTypeAtTopLevel(type);
    var typeRep = _emitType(
        // Avoid tagging a closure as Function? or Function*
        type.withDeclaredNullability(Nullability.nonNullable));
    if (type.typeParameters.isEmpty) {
      return _runtimeCall(lazy ? 'lazyFn(#, #)' : 'fn(#, #)', [fn, typeRep]);
    } else {
      var typeParameterDefaults = [
        for (var parameter in type.typeParameters)
          _emitType(parameter.defaultType)
      ];
      var defaultInstantiatedBounds =
          _emitConstList(const DynamicType(), typeParameterDefaults);
      return _runtimeCall(
          'gFn(#, #, #)', [fn, typeRep, defaultInstantiatedBounds]);
    }
  }

  /// Whether the expression for [type] can be evaluated at this point in the JS
  /// module.
  ///
  /// Types cannot be evaluated if they depend on something that hasn't been
  /// defined yet. For example:
  ///
  ///     C foo() => null;
  ///     class C {}
  ///
  /// If we're emitting the type information for `foo`, we cannot refer to `C`
  /// yet, so we must evaluate foo's type lazily.
  bool _canEmitTypeAtTopLevel(DartType type) {
    switch (type) {
      case InterfaceType():
        return !_pendingClasses!.contains(type.classNode) &&
            type.typeArguments.every(_canEmitTypeAtTopLevel);
      case FutureOrType():
        return !_pendingClasses!.contains(_coreTypes.deprecatedFutureOrClass) &&
            _canEmitTypeAtTopLevel(type.typeArgument);
      case FunctionType():
        // Generic functions are always safe to emit, because they're lazy until
        // type arguments are applied.
        if (type.typeParameters.isNotEmpty) return true;
        return _canEmitTypeAtTopLevel(type.returnType) &&
            type.positionalParameters.every(_canEmitTypeAtTopLevel) &&
            type.namedParameters.every((n) => _canEmitTypeAtTopLevel(n.type));
      case RecordType():
        return type.positional.every(_canEmitTypeAtTopLevel) &&
            type.named.every((n) => _canEmitTypeAtTopLevel(n.type));
      case TypedefType():
        return type.typeArguments.every(_canEmitTypeAtTopLevel);
      case ExtensionType():
        return _canEmitTypeAtTopLevel(type.extensionTypeErasure);
      case DynamicType():
      case VoidType():
      case NeverType():
      case NullType():
      case IntersectionType():
      case TypeParameterType():
      case StructuralParameterType():
        return true;
      case AuxiliaryType():
        throwUnsupportedAuxiliaryType(type);
      case InvalidType():
        throwUnsupportedInvalidType(type);
    }
  }

  /// Returns an expression that evaluates to the rti object from the dart:_rti
  /// library that represents [type].
  ///
  /// [emitJSInteropGenericClassTypeParametersAsAny] indicates that we should
  /// emit the statically declared type as a JS interop generic class's type
  /// argument (rather than substituting Any). Any is required for correctness
  /// in most cases except for uses in non-external JS interop factories.
  /// Note: This only applies to the old style package:js interop and isn't
  /// necessary for any forms of static JS interop.
  js_ast.Expression _emitType(DartType type,
      {bool emitJSInteropGenericClassTypeParametersAsAny = true}) {
    /// Returns an expression that evaluates a type [recipe] within the type
    /// [environment].
    ///
    /// At runtime the expression will evaluate to an rti object.
    js_ast.Expression emitRtiEval(
            js_ast.Expression environment, String recipe) =>
        js.call('#.#("$recipe")',
            [environment, _emitMemberName('_eval', memberClass: _rtiClass)]);

    /// Returns an expression that binds a type [parameter] within the type
    /// [environment].
    ///
    /// At runtime the expression will evaluate to an rti object that has been
    /// extended to include the provided [parameter].
    js_ast.Expression emitRtiBind(
        js_ast.Expression environment, TypeParameter parameter) {
      return js.call('#.#(#)', [
        environment,
        _emitMemberName('_bind', memberClass: _rtiClass),
        _emitTypeParameter(parameter)
      ]);
    }

    /// Returns an expression that evaluates a type [recipe] in a type
    /// [environment] resulting in an rti object.
    js_ast.Expression evalInEnvironment(
        DDCTypeEnvironment environment, String recipe) {
      switch (environment) {
        case EmptyTypeEnvironment():
          return js
              .call('#._Universe.eval(#._theUniverse(), "$recipe", true)', [
            _emitLibraryName(_rtiLibrary),
            _emitLibraryName(_rtiLibrary),
          ]);
        case BindingTypeEnvironment():
          js_ast.Expression env;
          if (environment.isSingleTypeParameter) {
            // An environment with a single type parameter can be simplified to
            // just that parameter.
            env = _emitTypeParameter(environment.functionTypeParameters.single);
            // Skip a no-op evaluation and just return the parameter.
            if (recipe == '0') return env;
          } else {
            var environmentTypes = environment.functionTypeParameters;
            // Create a dummy interface type to "hold" type arguments.
            env =
                emitRtiEval(_emitTypeParameter(environmentTypes.first), '@<0>');
            // Bind remaining type arguments.
            for (var i = 1; i < environmentTypes.length; i++) {
              env = emitRtiBind(env, environmentTypes[i]);
            }
          }
          return emitRtiEval(env, recipe);
        case RtiTypeEnvironment():
          // RTI type environments are already constructed and attached to the
          // provided RTI.
          var env = _rtiParam;
          return emitRtiEval(env, recipe);
        case ClassTypeEnvironment():
          // Class type environments are already constructed and attached to the
          // instance of a generic class.
          var env =
              js.call('#.instanceType(this)', [_emitLibraryName(_rtiLibrary)]);
          return emitRtiEval(env, recipe);
        case ExtendedClassTypeEnvironment():
          // Class type environments are already constructed and attached to the
          // instance of a generic class, but function type parameters need to
          // be bound.
          var env =
              js.call('#.instanceType(this)', [_emitLibraryName(_rtiLibrary)]);
          // Bind extra type parameters.
          for (var parameter in environment.functionTypeParameters) {
            env = emitRtiBind(env, parameter);
          }
          return emitRtiEval(env, recipe);
      }
      _typeCompilationError(type,
          'Unexpected DDCTypeEnvironment type (${environment.runtimeType}).');
    }

    var normalizedType =
        _futureOrNormalizer.normalize(type.extensionTypeErasure);
    try {
      var result = _typeRecipeGenerator.recipeInEnvironment(
          normalizedType, _currentTypeEnvironment,
          emitJSInteropGenericClassTypeParametersAsAny:
              emitJSInteropGenericClassTypeParametersAsAny);
      var typeRep =
          evalInEnvironment(result.requiredEnvironment, result.recipe);
      return typeRep;
    } on UnsupportedError catch (e) {
      _typeCompilationError(normalizedType, e.message ?? 'Unknown Error');
    }
  }

  js_ast.Expression _emitInvalidNode(Node node, [String message = '']) {
    if (message.isNotEmpty) message += ' ';
    return _runtimeCall('throwUnimplementedError(#)',
        [js.escapedString('node <${node.runtimeType}> $message`$node`')]);
  }

  /// Emits a reference to the class described by [type].
  ///
  /// The nullability of [type] is not considered because it is meaningless when
  /// describing a reference to the class itself.
  ///
  /// For generic classes, type arguments are not needed since they are
  /// resolved late via an RTI lookup.
  ///
  /// Note that for `package:js` types, this will emit the class we emitted
  /// using `_emitJSInteropClassNonExternalMembers`, and not the runtime type
  /// that we synthesize for `package:js` types.
  js_ast.Expression _emitClassRef(InterfaceType type) {
    var cls = type.classNode;
    _declareBeforeUse(cls);
    if (!_emittingClassExtends && type.typeArguments.isNotEmpty) {
      var genericName = _emitTopLevelNameNoExternalInterop(type.classNode);
      return js.call('#', [genericName]);
    }
    return _emitTopLevelNameNoExternalInterop(type.classNode);
  }

  Never _typeCompilationError(DartType type, String description) =>
      throw UnsupportedError('$description Encountered while compiling '
          '${_currentLibrary!.fileUri}, which contains the type: $type.');

  bool get _emittingClassExtends =>
      _currentClass != null && identical(_currentClass, _classEmittingExtends);

  /// Emits an expression that lets you access statics on a [type] from code.
  js_ast.Expression _emitConstructorName(InterfaceType type, Member c) {
    var isSyntheticDefault =
        c is Constructor && c.isSynthetic && c.name.text.isEmpty;
    // If it's an external constructor or synthetic default, use the JS
    // constructor.
    var jsConstructor = _emitJSInterop(type.classNode);
    if (jsConstructor != null && (c.isExternal || isSyntheticDefault)) {
      return jsConstructor;
    }
    // If it's non-external but belongs to an interop class, we want the class
    // reference we defined in `_emitJSInteropClassNonExternalMembers`.
    return js_ast.PropertyAccess(
        _emitClassRef(type), _constructorName(c.name.text));
  }

  /// Emits an expression that lets you access statics on [c] from code.
  ///
  /// If [isExternal] is false, emits the non-external name.
  js_ast.Expression _emitStaticClassName(Class c, bool isExternal) {
    _declareBeforeUse(c);
    return isExternal
        ? _emitTopLevelName(c)
        : _emitTopLevelNameNoExternalInterop(c);
  }

  js_ast.Identifier _emitTypeParameter(
      /* TypeParameter | StructuralParameter */ Object t) {
    assert(t is TypeParameter || t is StructuralParameter);
    return _emitIdentifier(getTypeParameterName(t));
  }

  /// Set incremental mode for expression compilation.
  ///
  /// Called for each expression compilation to set the incremental mode
  /// and clear referenced items.
  ///
  /// Sets all tables and internal structures to incremental mode so
  /// only referenced items will be emitted in a generated function.
  ///
  /// The compiler cannot revert to non-incremental mode, and requires the
  /// original module to be already emitted by the same compiler instance.
  void _setIncrementalMode() {
    if (!_moduleEmitted) {
      throw StateError(
          'Cannot run in incremental mode before module completion');
    }
    _incrementalModules.clear();
    _privateNames.clear();
    _symbolContainer.setIncrementalMode();
    _incrementalMode = true;

    _constTableCache = ModuleItemContainer<String>.asArray('C');
    _constLazyAccessors.clear();
    _constAliasCache.clear();

    _uriContainer = ModuleItemContainer<String>.asArray('I');

    _typeTable.typeContainer.setIncrementalMode();
  }

  /// Emits function after initial compilation.
  ///
  /// Emits function from kernel [functionNode] with name [name] in the context
  /// of [library] and [cls], after the initial compilation of the module is
  /// finished. For example, this happens in expression compilation during
  /// expression evaluation initiated by the user from the IDE and coordinated
  /// by the debugger.
  /// Triggers incremental mode, which only emits symbols, types, constants,
  /// libraries, and uris referenced in the expression compilation result.
  @override
  js_ast.Fun emitFunctionIncremental(List<ModuleItem> items, Library library,
      Class? cls, FunctionNode functionNode, String name) {
    // Setup context.
    _currentLibrary = library;
    _staticTypeContext.enterLibrary(_currentLibrary!);
    _currentClass = cls;
    // Generic parameters should be evaluated in a class environment if
    // provided. Otherwise we default to an empty type environment.
    if (cls != null) {
      _currentTypeEnvironment = ClassTypeEnvironment(cls.typeParameters);
    }

    // Keep all symbols in containers.
    _containerizeSymbols = true;

    // Set all tables to incremental mode, so we can only emit elements that
    // were referenced the compiled code for the expression.
    _setIncrementalMode();

    // Do not add formal parameter checks for the top-level synthetic function
    // generated for expression evaluation, as those parameters are a set of
    // variables from the current scope, and should already be checked in the
    // original code.
    _checkParameters = false;

    // Emit function while recoding elements accessed from tables.
    var fun = _emitFunction(functionNode, name);

    var extensionSymbols = <js_ast.Statement>[];
    _emitExtensionSymbols(extensionSymbols);

    // Add all elements from tables accessed in the function
    var body = js_ast.Block([
      ...extensionSymbols,
      ..._typeTable.dischargeBoundTypes(),
      ..._symbolContainer.emit(),
      ..._emitConstTable(),
      ..._uriContainer.emit(),
      ...fun.body.statements
    ]);

    // Import all necessary libraries, including libraries accessed from the
    // current module and libraries accessed from the type table.
    for (var library in _typeTable.incrementalLibraries()) {
      _setEmitIfIncrementalLibrary(library);
    }
    _emitImports(items);
    _emitExportsAsImports(items, _currentLibrary!);

    return js_ast.Fun(fun.params, body);
  }

  List<js_ast.Statement> _emitConstTable() {
    var constTable = <js_ast.Statement>[];
    if (_constLazyAccessors.isNotEmpty) {
      constTable
          .add(js.statement('const # = Object.create(null);', [_constTable]));

      constTable.add(_runtimeStatement(
          'defineLazy(#, { # })', [_constTable, _constLazyAccessors]));

      constTable.addAll(_constTableCache.emit());
    }
    return constTable;
  }

  js_ast.Fun _emitFunction(FunctionNode f, String? name,
      {SourceLocation? functionEnd, SourceLocation? functionBody}) {
    var savedTypeEnvironment = _currentTypeEnvironment;
    if (f.typeParameters.isNotEmpty) {
      _currentTypeEnvironment =
          _currentTypeEnvironment.extend(f.typeParameters);
    }
    var formals = _emitParameters(f);
    var typeFormals = _emitTypeFormals(f.typeParameters);

    var parent = f.parent;
    if (_reifyGenericFunction(parent is Member ? parent : null)) {
      formals.insertAll(0, typeFormals);
    }

    // TODO(jmesserly): need a way of determining if parameters are
    // potentially mutated in Kernel. For now we assume all parameters are.
    _enterFunction(name, formals, () => true);

    var block = js_ast.Block(_withCurrentFunction(f, () {
      final bodyPrefix = _emitArgumentInitializers(f, name);

      // Do the async transformation before adding parameter initialization
      // logic. Any parameter initialization should be performed synchronously
      // before the async body is evaluated.
      final bodyFn =
          js_ast.Fun(formals, js_ast.Block([_emitFunctionScopedBody(f)]));
      final rewrittenFunction = _rewriteAsyncFunction(
          bodyFn, f.asyncMarker, name, f.emittedValueType,
          functionEnd: functionEnd,
          functionBody: functionBody,
          bodyPrefix: bodyPrefix);
      formals = rewrittenFunction.params;
      return rewrittenFunction.body.statements;
    }));

    block = _exitFunction(formals, block);
    var fn = js_ast.Fun(formals, block);

    _currentTypeEnvironment = savedTypeEnvironment;
    return fn;
  }

  /// Transforms [fun]'s body to support async execution if the function is
  /// async, sync*, or async*.
  ///
  /// [bodyPrefix] will get prepended to the body of the rewritten function and
  /// any references to parameters within it will be replaced with the correct
  /// temporary ID for that parameter.
  js_ast.Fun _rewriteAsyncFunction(js_ast.Fun fun, AsyncMarker asyncMarker,
      String? name, DartType? asyncType,
      {SourceLocation? functionEnd,
      SourceLocation? functionBody,
      List<js_ast.Statement>? bodyPrefix}) {
    AsyncRewriterBase? asyncRewriter;
    final bodyName = _emitScopedId('t\$async${name ?? 'Body'}');
    switch (asyncMarker) {
      case AsyncMarker.Sync:
        break;
      case AsyncMarker.Async:
        asyncRewriter = AsyncRewriter(
            asyncStart: _emitTopLevelNameNoExternalInterop(_asyncStartMember),
            asyncAwait: _emitTopLevelNameNoExternalInterop(_asyncAwaitMember),
            asyncReturn: _emitTopLevelNameNoExternalInterop(_asyncReturnMember),
            asyncRethrow:
                _emitTopLevelNameNoExternalInterop(_asyncRethrowMember),
            completerFactory:
                _emitTopLevelNameNoExternalInterop(_asyncMakeCompleterMember),
            completerFactoryTypeArguments: [
              _emitType(asyncType!),
            ],
            wrapBody:
                _emitTopLevelNameNoExternalInterop(_asyncWrapJsFunctionMember),
            bodyName: bodyName);
      case AsyncMarker.SyncStar:
        asyncRewriter = SyncStarRewriter(
            makeSyncStarIterable:
                _emitTopLevelNameNoExternalInterop(_syncStarMakeIterableMember),
            syncStarIterableTypeArgument: _emitType(asyncType!),
            iteratorCurrentValueProperty: _emitMemberName('_current',
                member: _syncStarIteratorCurrentMember),
            iteratorDatumProperty:
                _emitMemberName('_datum', member: _syncStarIteratorDatumMember),
            yieldStarSelector: _emitMemberName('_yieldStar',
                member: _syncStarIteratorYieldStarMember),
            bodyName: bodyName);
      case AsyncMarker.AsyncStar:
        asyncRewriter = AsyncStarRewriter(
            asyncStarHelper:
                _emitTopLevelNameNoExternalInterop(_asyncStarHelperMember),
            streamOfController: _emitTopLevelNameNoExternalInterop(
                _asyncStreamOfControllerMember),
            newController: _emitTopLevelNameNoExternalInterop(
                _asyncMakeAsyncStarStreamControllerMember),
            newControllerTypeArguments: [_emitType(asyncType!)],
            yieldExpression:
                _emitStaticGet(_asyncIterationMarkerYieldSingleMember),
            yieldStarExpression:
                _emitStaticGet(_asyncIterationMarkerYieldStarMember),
            wrapBody:
                _emitTopLevelNameNoExternalInterop(_asyncWrapJsFunctionMember),
            bodyName: bodyName);
    }
    if (asyncRewriter != null) {
      return asyncRewriter.rewrite(fun, functionBody, functionEnd,
          bodyPrefix: bodyPrefix);
    } else if (bodyPrefix != null) {
      fun.body.statements.insertAll(0, bodyPrefix);
    }
    return fun;
  }

  js_ast.Parameter _emitParameter(VariableDeclaration node,
      {bool withoutInitializer = false}) {
    var initializer = node.initializer;
    var id = _emitVariableDef(node);
    if (initializer == null || withoutInitializer) return id;
    return js_ast.DestructuredVariable(
        name: id, defaultValue: _visitExpression(initializer));
  }

  List<js_ast.Parameter> _emitParameters(FunctionNode f,
      {bool isForwarding = false}) {
    // Destructure optional positional parameters in place.
    // Given:
    //  - (arg1, arg2, [opt1, opt2 = def2])
    // Emit:
    //  - (arg1, arg2, opt1 = null, opt2 = def2)
    // Note, if [isForwarding] is set, omit initializers as this actually a
    // forwarded call not a parameter list. E.g., the second in:
    //  - foo(arg1, opt1 = def1) => super(arg1, opt1).
    var positional = f.positionalParameters;
    var result = List<js_ast.Parameter>.of(positional
        .map((p) => _emitParameter(p, withoutInitializer: isForwarding)));
    if (positional.isNotEmpty &&
        f.requiredParameterCount == positional.length &&
        positional.last.annotations.any(isJsRestAnnotation)) {
      result.last = js_ast.RestParameter(result.last as js_ast.Identifier);
    }
    if (f.namedParameters.isNotEmpty) result.add(_namedArgumentTemp);
    return result;
  }

  List<js_ast.Identifier> _emitTypeFormals(
      List< /*TypeParameter | StructuralParameter */ Object> typeFormals) {
    assert(typeFormals is List<TypeParameter> ||
        typeFormals is List<StructuralParameter>);
    return typeFormals
        .map((t) => _emitIdentifier(getTypeParameterName(t)))
        .toList();
  }

  List<js_ast.Statement> _withCurrentFunction(
      FunctionNode fn, List<js_ast.Statement> Function() action) {
    var savedFunction = _currentFunction;
    _currentFunction = fn;
    if (_isDartLibrary(_currentLibrary!, '_rti') ||
        _isSdkInternalRuntime(_currentLibrary!)) {
      _nullableInference.treatDeclaredTypesAsSound = true;
    }
    _nullableInference.enterFunction(fn);
    var result = _withLetScope(action);
    _nullableInference.exitFunction(fn);
    _nullableInference.treatDeclaredTypesAsSound = false;

    _currentFunction = savedFunction;
    return result;
  }

  T _superDisallowed<T>(T Function() action) {
    var savedSuperAllowed = _superAllowed;
    _superAllowed = false;
    var result = action();
    _superAllowed = savedSuperAllowed;
    return result;
  }

  /// Executes [action] in context of the current [member].
  ///
  /// Saves and restores important context information about the member
  /// that can be used to generate code inside the body of the member.
  T _withMethodDeclarationContext<T>(Procedure member, T Function() action) {
    // Mixin applications require using 'super' in calls to members of
    // the super class. Store this information to disable non-virtual
    // super field access optimization when compiling the member body.
    var savedOptimizeNonVirtualFieldAccess = _optimizeNonVirtualFieldAccess;
    _optimizeNonVirtualFieldAccess =
        member.stubKind != ProcedureStubKind.ConcreteMixinStub;
    var result = action();
    _optimizeNonVirtualFieldAccess = savedOptimizeNonVirtualFieldAccess;
    return result;
  }

  /// Returns true if the underlying type does not accept a null value.
  bool _mustBeNonNullable(DartType type) =>
      type.nullability == Nullability.nonNullable;

  /// Returns `true` when an additional null check is needed because of the
  /// null safety compile mode, the null safety migration status of the current
  /// library and the provided [type] with its [annotations].
  bool _requiresExtraNullCheck(DartType type, List<Expression> annotations) =>
      !_options.soundNullSafety &&
      // Libraries that haven't been migrated to null safety represent
      // non-nullable as legacy.
      _currentLibrary!.nonNullable == Nullability.nonNullable &&
      _mustBeNonNullable(type) &&
      !_annotatedNotNull(annotations) &&
      // Trust the nullability of types in the dart:_rti library.
      !_isDartLibrary(_currentLibrary!, '_rti');

  /// Returns a null check for [value] that if fails produces an error message
  /// containing the [location] and [name] of the original value being checked.
  ///
  /// This is used to generate checks for non-nullable parameters when running
  /// with weak null safety. The checks can be silent, warn, or throw, depending
  /// on the flags set in the SDK at runtime.
  js_ast.Statement _nullSafetyParameterCheck(
      js_ast.Identifier value, Location? location, String? name) {
    // TODO(nshahan): Remove when weak mode null safety assertions are no longer
    // supported.
    // The check on `field.setterType` is per:
    // https://github.com/dart-lang/language/blob/master/accepted/2.12/nnbd/feature-specification.md#automatic-debug-assertion-insertion
    var condition = js.call('# == null', [value]);
    // Offsets are not available for compiler-generated variables
    // Get the best available location even if the offset is missing.
    // https://github.com/dart-lang/sdk/issues/34942
    return js.statement(' if (#) #;', [
      condition,
      _runtimeCall('nullFailed(#, #, #, #)', [
        location != null
            ? _cacheUri(location.file.toString())
            : js_ast.LiteralNull(),
        js.number(location?.line ?? -1),
        js.number(location?.column ?? -1),
        js.escapedString('$name')
      ])
    ]);
  }

  /// Emits argument initializers, which handles optional/named args, as well
  /// as generic type checks needed due to our covariance.
  List<js_ast.Statement> _emitArgumentInitializers(
      FunctionNode f, String? name) {
    var body = <js_ast.Statement>[];

    _emitCovarianceBoundsCheck(f.typeParameters, body);

    void initParameter(VariableDeclaration p, js_ast.Identifier jsParam) {
      // When the parameter is covariant, insert the null check before the
      // covariant cast to avoid a TypeError when testing equality with null.
      if (name == '==') {
        // In Dart `operator ==` methods are not called with a null argument.
        // This is handled before calling them. For performance reasons, we push
        // this check inside the method, to simplify our `equals` helper.
        //
        // TODO(jmesserly): in most cases this check is not necessary, because
        // the Dart code already handles it (typically by an `is` check).
        // Eliminate it when possible.
        body.add(js.statement('if (# == null) return false;', [jsParam]));
      }
      if (isCovariantParameter(p)) {
        var castExpr = _emitCast(jsParam, p.type);
        if (!identical(castExpr, jsParam)) body.add(castExpr.toStatement());
      }

      if (name == '==') return;

      if (_annotatedNullCheck(p.annotations)) {
        body.add(_nullParameterCheck(jsParam));
      } else if (_requiresExtraNullCheck(p.type, p.annotations)) {
        body.add(_nullSafetyParameterCheck(jsParam, p.location, p.name));
      }
    }

    for (var p in f.positionalParameters) {
      var jsParam = _emitVariableRef(p);
      if (_checkParameters) {
        initParameter(p, jsParam);
      }
    }
    for (var p in f.namedParameters) {
      // Parameters will be passed using their real names, not the (possibly
      // renamed) local variable.
      var jsParam = _emitVariableDef(p);
      var paramName = _propertyName(p.name!);
      var defaultValue = _defaultParamValue(p);
      body.add(js.statement('let # = # && # ? #.# : #;', [
        jsParam,
        _namedArgumentTemp,
        _namedArgumentProbe(paramName),
        _namedArgumentTemp,
        paramName,
        defaultValue,
      ]));

      if (_checkParameters) {
        initParameter(p, jsParam);
      }
    }

    // '_checkParameters = false' is only needed once, while processing formal
    // parameters of the synthetic function from expression evaluation - it
    // will be called from emitFunctionIncremental, which is a top-level API
    // for expression compilation.
    // Here we either are done with processing those formals, or compiling
    // something else (in which case _checkParameters is already true).
    _checkParameters = true;
    return body;
  }

  bool _annotatedNullCheck(List<Expression> annotations) =>
      annotations.any(_nullableInference.isNullCheckAnnotation);

  bool _annotatedNotNull(List<Expression> annotations) =>
      annotations.any(_nullableInference.isNotNullAnnotation);

  bool _reifyGenericFunction(Member? m) =>
      m == null ||
      // JS interop members should not pass type arguments.
      !isJsMember(m) &&
          !(m.enclosingLibrary.importUri.isScheme('dart') &&
              m.annotations.any((a) =>
                  isBuiltinAnnotation(a, '_js_helper', 'NoReifyGeneric')));

  js_ast.Statement _nullParameterCheck(js_ast.Expression param) {
    var call = _runtimeCall('argumentError((#))', [param]);
    return js.statement('if (# == null) #;', [param, call]);
  }

  js_ast.Expression _defaultParamValue(VariableDeclaration p) {
    if (p.initializer != null) {
      return _visitExpression(p.initializer!);
    } else {
      return js_ast.LiteralNull();
    }
  }

  /// Returns a test for the existence of [propertyName] in the named argument
  /// package.
  js_ast.Expression _namedArgumentProbe(js_ast.LiteralString propertyName) =>
      // If the name collides with the names in the native JavaScript object
      // prototype then use a slower but more direct test to avoid
      // accidentally finding a value up the prototype chain.
      js_ast.objectProperties.contains(propertyName.valueWithoutQuotes)
          ? _runtimeCall('hOP.call(#, #)', [_namedArgumentTemp, propertyName])
          : js.call('# in #', [propertyName, _namedArgumentTemp]);

  void _emitCovarianceBoundsCheck(
      List< /* TypeParameter | StructuralParameter */ Object> typeFormals,
      List<js_ast.Statement> body) {
    assert(typeFormals is List<TypeParameter> ||
        typeFormals is List<StructuralParameter>);
    for (var t in typeFormals) {
      bool? isCovariantByClass;
      DartType bound;
      String name;
      DartType typeParameterType;
      if (t is TypeParameter) {
        isCovariantByClass = t.isCovariantByClass;
        bound = t.bound.extensionTypeErasure;
        name = t.name!;
        typeParameterType = TypeParameterType(t, Nullability.undetermined);
      } else {
        t as StructuralParameter;
        bound = t.bound.extensionTypeErasure;
        name = t.name!;
        typeParameterType =
            StructuralParameterType(t, Nullability.undetermined);
      }

      if (isCovariantByClass != null &&
          isCovariantByClass &&
          !_types.isTop(bound)) {
        body.add(_runtimeStatement('checkTypeBound(#, #, #)', [
          _emitType(typeParameterType),
          _emitType(bound),
          _propertyName(name)
        ]));
      }
    }
  }

  js_ast.Statement _visitStatement(Statement s) {
    var result = s.accept(this);

    // In most cases, a Dart expression statement with a child expression
    // compile to a JS expression statement with a child expression.
    //
    //   ExpressionStatement                         js_ast.ExpressionStatement
    //            |           --> compiles to -->                 |
    //        Expression                                  js_ast.Expression
    //
    // Both the expression statement and child expression nodes contain their
    // own source location information.
    //
    // In the case of a debugger() call, the code compiles to a single node.
    //
    //   ExpressionStatement                         js_ast.DebuggerStatement
    //            |           --> compiles to -->
    //        Expression
    //
    // The js_ast.DebuggerStatement already has the correct source information
    // attached so we avoid overwriting with the incorrect source location from
    // [s].
    // TODO(jmesserly): is the `is! Block` still necessary?
    if (!(s is Block || result is js_ast.DebuggerStatement)) {
      result.sourceInformation ??= _nodeStart(s);
    }

    // The statement might be the target of a break or continue with a label.
    var name = _labelNames[s];
    if (name != null) result = js_ast.LabeledStatement(name, result);
    return result;
  }

  js_ast.Statement _emitFunctionScopedBody(FunctionNode f) {
    var jsBody = _visitStatement(f.body!);
    return _emitScopedBody(f, jsBody);
  }

  js_ast.Statement _emitScopedBody(FunctionNode f, js_ast.Statement body) {
    if (f.positionalParameters.isNotEmpty || f.namedParameters.isNotEmpty) {
      // Handle shadowing of parameters by local variables, which is allowed in
      // Dart but not in JS.
      //
      // We need this for all function types, including generator-based ones
      // (sync*/async/async*). Our code generator assumes it can emit names for
      // named argument initialization, and sync* functions also emit locally
      // modified parameters into the function's scope.
      var parameterNames = {
        for (var p in f.positionalParameters) p.name!,
        for (var p in f.namedParameters) p.name!,
      };

      return body.toScopedBlock(parameterNames);
    }
    return body;
  }

  /// Visits [nodes] with [_visitExpression].
  List<js_ast.Expression> _visitExpressionList(Iterable<Expression> nodes) {
    return nodes.map(_visitExpression).toList();
  }

  /// Generates an expression for a boolean conversion context (if, while, &&,
  /// etc.), where conversions and null checks are implemented via `dart.test`
  /// to give a more helpful message.
  // TODO(sra): When nullablility is available earlier, it would be cleaner to
  // build an input AST where the boolean conversion is a single AST node.
  js_ast.Expression _visitTest(Expression node) {
    if (node is Not) {
      return visitNot(node);
    }
    if (node is LogicalExpression) {
      js_ast.Expression shortCircuit(String code) {
        return js.call(code, [_visitTest(node.left), _visitTest(node.right)]);
      }

      var op = node.operatorEnum;
      if (op == LogicalExpressionOperator.AND) return shortCircuit('# && #');
      if (op == LogicalExpressionOperator.OR) return shortCircuit('# || #');
    }

    if (node is AsExpression && node.isTypeError) {
      assert(node.getStaticType(_staticTypeContext) ==
          _types.coreTypes.boolRawType(_currentLibrary!.nonNullable));
      return _runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
    }

    var result = _visitExpression(node);
    if (_isNullable(node)) result = _runtimeCall('test(#)', [result]);
    return result;
  }

  js_ast.Expression _visitExpression(Expression e) {
    if (e is ConstantExpression) {
      return visitConstant(e.constant);
    }
    var result = e.accept(this);
    result.sourceInformation ??= _nodeStart(e);
    return result;
  }

  /// Gets the start position of [node] for use in source mapping.
  ///
  /// This is the most common kind of marking, and is used for most expressions
  /// and statements.
  SourceLocation? _nodeStart(TreeNode node) => node is StringConcatenation
      // Manually selecting the location of the first element to work around the
      // location on the StringConcatenation node that points to the end of
      // String. See https://github.com/dart-lang/sdk/issues/55690.
      ? _toSourceLocation(node.expressions.first.fileOffset)
      : _toSourceLocation(node.fileOffset);

  /// Gets the end position of [node] for use in source mapping.
  ///
  /// This is mainly used for things that compile to JS functions. JS wants a
  /// marking on the end of all functions for stepping purposes.
  ///
  /// This can be used to complete a hover span, when we know the start position
  /// has already been emitted. For example, `foo.bar` we only need to mark the
  /// end of `.bar` to ensure `foo.bar` has a hover tooltip.
  NodeEnd? _nodeEnd(int endOffset) {
    var loc = _toSourceLocation(endOffset);
    return loc != null ? NodeEnd(loc) : null;
  }

  /// Combines [_nodeStart] with the variable name length to produce a hoverable
  /// span for the variable.
  //
  // TODO(jmesserly): we need a lot more nodes to support hover.
  NodeSpan? _variableSpan(int offset, int nameLength) {
    var start = _toSourceLocation(offset);
    var end = _toSourceLocation(offset + nameLength);
    return start != null && end != null ? NodeSpan(start, end) : null;
  }

  SourceLocation? _toSourceLocation(int offset) {
    if (offset == -1) return null;
    var fileUri = _currentUri;
    if (fileUri == null) return null;
    try {
      var loc = _component.getLocation(fileUri, offset);
      if (loc == null || loc.line < 0) return null;
      return SourceLocation(offset,
          sourceUrl: fileUri, line: loc.line - 1, column: loc.column - 1);
    } on StateError catch (_) {
      // TODO(jmesserly): figure out why this is throwing. Perhaps the file URI
      // and offset are mismatched and don't correspond to the same source?
      return null;
    } on RangeError catch (_) {
      return null;
    }
  }

  /// Adds a hover comment for Dart node using JS expression [expr], where
  /// that expression would not otherwise not be generated into source code.
  ///
  /// For example, top-level and static fields are defined as lazy properties,
  /// on the library/class, so their access expressions do not appear in the
  /// source code.
  HoverComment? _hoverComment(
      js_ast.Expression expr, int offset, int nameLength) {
    var start = _toSourceLocation(offset);
    var end = _toSourceLocation(offset + nameLength);
    return start != null && end != null ? HoverComment(expr, start, end) : null;
  }

  @override
  js_ast.Statement visitExpressionStatement(ExpressionStatement node) {
    var expr = node.expression;
    if (expr is StaticInvocation) {
      if (isInlineJS(expr.target)) {
        return _emitInlineJSCode(expr).toStatement();
      }
      if (_isDebuggerCall(expr.target)) {
        return _emitDebuggerCall(expr).toStatement();
      }
    }
    return _visitExpression(expr).toStatement();
  }

  @override
  js_ast.Statement visitBlock(Block node) {
    // If this is the block body of a function, don't mark it as a separate
    // scope, because the function is the scope. This avoids generating an
    // unnecessary nested block.
    //
    // NOTE: we do sometimes need to handle this because Dart and JS rules are
    // slightly different (in Dart, there is a nested scope), but that's handled
    // by _emitSyncFunctionBody.
    var isScope = !identical(node.parent, _currentFunction);
    return js_ast.Block(node.statements.map(_visitStatement).toList(),
        isScope: isScope);
  }

  @override
  js_ast.Statement visitEmptyStatement(EmptyStatement node) =>
      js_ast.EmptyStatement();

  @override
  js_ast.Statement visitAssertBlock(AssertBlock node) {
    // AssertBlocks are introduced by the VM-specific async elimination
    // transformation.  We do not expect them to arise here.
    throw UnsupportedError('compilation of an assert block');
  }

  // Replace a string `uri` literal with a cached top-level variable containing
  // the value to reduce overall code size.
  js_ast.Expression _cacheUri(String uri) {
    if (!_uriContainer.contains(uri)) {
      _uriContainer[uri] = js_ast.LiteralString('"$uri"');
    }
    _uriContainer.setEmitIfIncremental(uri);
    return _uriContainer.access(uri);
  }

  @override
  js_ast.Statement visitAssertStatement(AssertStatement node) {
    if (!_options.enableAsserts) return js_ast.EmptyStatement();
    var condition = node.condition;
    var conditionType =
        condition.getStaticType(_staticTypeContext).extensionTypeErasure;
    var jsCondition = _visitExpression(condition);

    if (conditionType != _coreTypes.boolLegacyRawType &&
        conditionType != _coreTypes.boolNullableRawType &&
        conditionType != _coreTypes.boolNonNullableRawType) {
      jsCondition = _runtimeCall('dtest(#)', [jsCondition]);
    } else if (_isNullable(condition)) {
      // TODO(nshahan): Is this branch even reachable in null safe code?
      jsCondition = _runtimeCall('test(#)', [jsCondition]);
    }

    SourceLocation? location;
    late String conditionSource;
    var assertLocation = node.location;
    if (assertLocation != null) {
      var fileUri = assertLocation.file;
      var source = node.enclosingComponent!.uriToSource[fileUri]!.text;
      conditionSource =
          source.substring(node.conditionStartOffset, node.conditionEndOffset);
      // Assertions that appear in debugger expressions have a synthetic Uri
      // that is different than the current library where the expression will
      // be evaluated.
      var savedUri = _currentUri;
      _currentUri = fileUri;
      location = _toSourceLocation(node.conditionStartOffset)!;
      _currentUri = savedUri;
    } else {
      // If the location is ever null, only show the error with the condition
      // AST instead of the source.
      conditionSource = node.condition.toString();
    }
    return js.statement(' if (!#) #;', [
      jsCondition,
      _runtimeCall('assertFailed(#, #, #, #, #)', [
        if (node.message == null)
          js_ast.LiteralNull()
        else
          _visitExpression(node.message!),
        if (location == null)
          _cacheUri('<unknown source>')
        else
          _cacheUri(location.sourceUrl.toString()),
        // Lines and columns are typically printed with 1 based indexing.
        js.number(location == null ? -1 : location.line + 1),
        js.number(location == null ? -1 : location.column + 1),
        js.escapedString(conditionSource),
      ])
    ]);
  }

  bool _isBreakable(Statement stmt) {
    // These are conservatively the things that compile to things that can be
    // the target of a break without a label.
    return stmt is ForStatement ||
        stmt is WhileStatement ||
        stmt is DoStatement ||
        stmt is ForInStatement ||
        stmt is SwitchStatement;
  }

  @override
  js_ast.Statement visitLabeledStatement(LabeledStatement node) {
    List<LabeledStatement>? saved;
    // If the effective target is known then this statement is either contained
    // in a labeled statement or a loop.  It has already been processed when
    // the enclosing statement was visited.
    if (!_effectiveTargets.containsKey(node)) {
      // Find the effective target by bypassing and collecting labeled
      // statements.
      var statements = [node];
      var target = node.body;
      while (target is LabeledStatement) {
        var labeled = target;
        statements.add(labeled);
        target = labeled.body;
      }
      for (var statement in statements) {
        _effectiveTargets[statement] = target;
      }

      // If the effective target will compile to something that can have a
      // break from it without a label (e.g., a loop but not a block), then any
      // of the labeled statements can have a break from them by breaking from
      // the effective target.  Otherwise breaks will need a label and a break
      // without a label can still target an outer breakable so the list of
      // current break targets does not change.
      if (_isBreakable(target)) {
        saved = _currentBreakTargets;
        _currentBreakTargets = statements;
      }
    }

    var result = _visitStatement(node.body);
    if (saved != null) _currentBreakTargets = saved;
    return result;
  }

  @override
  js_ast.Statement visitBreakStatement(BreakStatement node) {
    // Switch statements with continue labels must explicitly break to their
    // implicit label due to their being wrapped in a loop.
    if (_inLabeledContinueSwitch &&
        _switchLabelStates.containsKey(node.target.body)) {
      return js_ast.Break(_switchLabelStates[node.target.body]!.label);
    }
    // Can it be compiled to a break without a label?
    if (_currentBreakTargets.contains(node.target)) {
      return js_ast.Break(null);
    }
    // Can it be compiled to a continue without a label?
    if (_currentContinueTargets.contains(node.target)) {
      return js_ast.Continue(null);
    }

    // Ensure the effective target is labeled.  Labels are named globally per
    // Kernel binary.
    //
    // TODO(markzipan): Retrieve the real label name with source offsets
    var target = _effectiveTargets[node.target];
    var name = _labelNames[target!];
    if (name == null) _labelNames[target] = name = 'L${_labelNames.length}';

    // It is a break if the target labeled statement encloses the effective
    // target.
    Statement current = node.target;
    while (current is LabeledStatement) {
      current = current.body;
    }
    if (identical(current, target)) {
      return js_ast.Break(name);
    }
    // Otherwise it is a continue.
    return js_ast.Continue(name);
  }

  // Labeled loop bodies can be the target of a continue without a label
  // (targeting the loop).  Find the outermost non-labeled statement starting
  // from body and record all the intermediate labeled statements as continue
  // targets.
  Statement _effectiveBodyOf(Statement loop, Statement body) {
    // In a loop whose body is not labeled, this list should be empty because
    // it is not possible to continue to an outer loop without a label.
    _currentContinueTargets = <LabeledStatement>[];
    while (body is LabeledStatement) {
      var labeled = body;
      _currentContinueTargets.add(labeled);
      _effectiveTargets[labeled] = loop;
      body = labeled.body;
    }
    return body;
  }

  T _translateLoop<T extends js_ast.Statement>(
      Statement node, T Function() action) {
    List<LabeledStatement>? savedBreakTargets;
    if (_currentBreakTargets.isNotEmpty &&
        _effectiveTargets[_currentBreakTargets.first] != node) {
      // If breaking without a label targets some other (outer) loop, then
      // this loop prevents breaking to that loop without a label.  This loop
      // was not labeled for a break in Kernel, otherwise it would be the
      // effective target of the current break targets, so it is not itself the
      // target of a break.
      savedBreakTargets = _currentBreakTargets;
      _currentBreakTargets = <LabeledStatement>[];
    }
    var savedContinueTargets = _currentContinueTargets;
    var result = action();
    if (savedBreakTargets != null) _currentBreakTargets = savedBreakTargets;
    _currentContinueTargets = savedContinueTargets;
    return result;
  }

  @override
  js_ast.While visitWhileStatement(WhileStatement node) {
    return _translateLoop(node, () {
      var condition = _visitTest(node.condition);
      var body = _visitScope(_effectiveBodyOf(node, node.body));
      return js_ast.While(condition, body);
    });
  }

  @override
  js_ast.Do visitDoStatement(DoStatement node) {
    return _translateLoop(node, () {
      var body = _visitScope(_effectiveBodyOf(node, node.body));
      var condition = _visitTest(node.condition);
      return js_ast.Do(body, condition);
    });
  }

  @override
  js_ast.Statement visitForStatement(ForStatement node) {
    return _translateLoop(node, () {
      js_ast.VariableInitialization emitForInitializer(VariableDeclaration v) =>
          js_ast.VariableInitialization(_emitVariableDef(v),
              _visitInitializer(v.initializer, v.annotations));

      if (node.variables.any(containsFunctionExpression)) {
        return _rewriteAsWhile(node);
      }
      var init = node.variables.map(emitForInitializer).toList();
      var initList =
          init.isEmpty ? null : js_ast.VariableDeclarationList('let', init);
      var updates = node.updates;
      js_ast.Expression? update;
      if (updates.isNotEmpty) {
        update = js_ast.Expression.binary(
                updates.map(_visitExpression).toList(), ',')
            .toVoidExpression();
      }
      var condition =
          node.condition != null ? _visitTest(node.condition!) : null;
      var body = _visitScope(_effectiveBodyOf(node, node.body));

      return js_ast.For(initList, condition, update, body);
    });
  }

  /// Rewrites a `for(;;)` style loop as a while loop to produce the correct
  /// semantics when loop variable initialziers contain function expressions
  /// that close over other loop variables.
  ///
  /// The Dart semantics expect that every loop iteration gets fresh loop
  /// variables that can be closed over. The initialization is only executed
  /// for the first iteration. In later iterations, the fresh loop variables are
  /// initalized to the values from the end of the previous iteration.
  ///
  /// These semantics differ from JavaScript when there are closures capturing
  /// loop variables so the simple lowering doesn't work as expected.
  ///
  /// A for loop like:
  ///
  /// ```
  /// for(var v1 = init1, v2 = init2; condition; updates) { body }
  /// ```
  ///
  /// Produces a rewrite like:
  ///
  /// ```
  /// var initFlag = true;
  /// var prev_v1, prev_v2;
  /// while (true) {
  ///   var v1, v2;
  ///   if (initFlag) {
  ///     initFlag = false;
  ///     v1 = inti1;
  ///     v2 = init2;
  ///   } else {
  ///     v1 = prev_v1;
  ///     v2 = prev_v2;
  ///     updates;
  ///   }
  ///   if (!condition) break;
  ///   body;
  ///   prev_v1 = v1;
  ///   prev_v2 = v2;
  /// }
  /// ```
  js_ast.Statement _rewriteAsWhile(ForStatement node) {
    var initFlagTempId = _emitScopedId('t#_init');
    var loopVariableIds = {
      for (var variable in node.variables) variable: _emitVariableDef(variable),
    };
    var prevVariableTempIds = {
      for (var variable in node.variables)
        variable: _emitScopedId('t#_prev_${variable.name!}'),
    };
    var inits = js_ast.Block([
      // Set init flag to false so the initialization only happens on the first
      // iteration of the while loop.
      js.statement('# = false;', [initFlagTempId]),
      // Initialize fresh loop variables to initial values.
      for (var variable in node.variables)
        js.statement('# = #;', [
          loopVariableIds[variable]!,
          _visitInitializer(variable.initializer, variable.annotations)
        ]),
    ]);
    var prevInits = js_ast.Block([
      // Intialize fresh loop variables with the value from the previous
      // iteration.
      for (var variable in node.variables)
        js.statement('# = #;',
            [loopVariableIds[variable], prevVariableTempIds[variable]]),
      // Original update expressions.
      for (var update in node.updates) _visitExpression(update).toStatement(),
    ]);
    return js_ast.Block([
      // Create temporary variables for the intialization flag and previous
      // loop variables.
      js_ast.VariableDeclarationList('let', [
        js_ast.VariableInitialization(initFlagTempId, js_ast.LiteralBool(true)),
        for (var variable in node.variables)
          js_ast.VariableInitialization(prevVariableTempIds[variable]!, null),
      ]).toStatement(),
      // The for loop transformed into a while loop.
      js_ast.While(
          js_ast.LiteralBool(true),
          js_ast.Block([
            // Create fresh loop variables every iteration.
            if (node.variables.isNotEmpty)
              js_ast.VariableDeclarationList('let', [
                for (var variable in node.variables)
                  js_ast.VariableInitialization(
                      loopVariableIds[variable]!, null)
              ]).toStatement(),
            // Initialize loop variables.
            js_ast.If(initFlagTempId, inits, prevInits),
            // Loop condition guard.
            if (node.condition != null)
              js.statement('if (!#) break;', [_visitTest(node.condition!)])
                ..sourceInformation = _nodeStart(node.condition!),
            // Original loop body.
            _visitScope(_effectiveBodyOf(node, node.body)),
            // Save previous loop variables
            for (var variable in node.variables)
              js.statement('# = #;',
                  [prevVariableTempIds[variable]!, _emitVariableRef(variable)])
                // Map these locations to the variable declaration so stepping
                // in the Dart debugger doesn't jump to the previous line when
                // stepping.
                ..sourceInformation = _nodeStart(variable),
          ]))
        // The while loop gets mapped to the orginal for loop location.
        ..sourceInformation = _nodeStart(node),
    ])
      // Clear the source mapping on the outer block so it doesn't automatically
      // get mapped to the for loop node in _visitStatement.
      ..sourceInformation = continueSourceMap;
  }

  @override
  js_ast.Statement visitForInStatement(ForInStatement node) {
    return _translateLoop(node, () {
      if (node.isAsync) {
        return _emitAwaitFor(node);
      }
      var iterable = _visitExpression(node.iterable);
      var body = _visitScope(_effectiveBodyOf(node, node.body));

      var init = js.call('let #', _emitVariableDef(node.variable));
      if (_annotatedNullCheck(node.variable.annotations)) {
        body = js_ast.Block(
            [_nullParameterCheck(_emitVariableRef(node.variable)), body]);
      }

      if (node.variable.name != null &&
          js_ast.variableIsReferenced(node.variable.name!, iterable)) {
        var temp = _emitScopedId('iter');
        return js_ast.Block([
          iterable.toVariableDeclaration(temp),
          js_ast.ForOf(init, temp, body)
        ]);
      }
      return js_ast.ForOf(init, iterable, body);
    });
  }

  js_ast.Statement _emitAwaitFor(ForInStatement node) {
    // Emits `await for (var value in stream) ...`, which desugars as:
    //
    // var iter = new StreamIterator(stream);
    // try {
    //   while (await iter.moveNext()) {
    //     var value = iter.current;
    //     ...
    //   }
    // } finally {
    //   await iter.cancel();
    // }
    //
    // Like the Dart VM, we call cancel() always, as it's safe to call if the
    // stream has already been cancelled.
    //
    // TODO(jmesserly): we may want a helper if these become common. For now the
    // full desugaring seems okay.
    var streamIterator = _coreTypes.rawType(
        _asyncStreamIteratorClass, _currentLibrary!.nonNullable);
    var streamIteratorRti = _emitType(streamIterator);
    var createStreamIter = js_ast.Call(
        _emitConstructorName(
            streamIterator,
            _asyncStreamIteratorClass.procedures
                .firstWhere((p) => p.isFactory && p.name.text == '')),
        [streamIteratorRti, _visitExpression(node.iterable)]);

    var iter = _emitScopedId('iter');

    var savedContinueTargets = _currentContinueTargets;
    var savedBreakTargets = _currentBreakTargets;
    _currentContinueTargets = <LabeledStatement>[];
    _currentBreakTargets = <LabeledStatement>[];
    var loopStmt = js.statement('while (#) { let # = #.current; #; }', [
      js_ast.Await(js.call('#.moveNext()', iter))
        ..sourceInformation = _nodeStart(node.variable),
      _emitVariableDef(node.variable),
      iter,
      _visitStatement(node.body)
    ]);

    // Any label on the Dart loop statement should target the inner loop rather
    // than the try-block we will wrap it in.
    final loopLabelName = _labelNames.remove(node);
    if (loopLabelName != null) {
      loopStmt = js_ast.LabeledStatement(loopLabelName, loopStmt);
    }

    var awaitForStmt = js_ast.Block([
      js_ast.ExpressionStatement(js_ast.VariableDeclarationList(
          'let', [js_ast.VariableInitialization(iter, createStreamIter)])
        ..sourceInformation = _nodeStart(node.iterable)),
      js.statement('try { # } finally { #; }', [
        loopStmt,
        js_ast.Await(js.call('#.cancel()', iter))
          ..sourceInformation = _nodeStart(node.variable)
      ])
    ], isScope: true);

    _currentContinueTargets = savedContinueTargets;
    _currentBreakTargets = savedBreakTargets;
    return awaitForStmt;
  }

  @override
  js_ast.Statement visitSwitchStatement(SwitchStatement node) {
    // Switches with labeled continues are generated as an infinite loop with
    // an explicit variable for holding the switch's next case state and an
    // explicit label. Any implicit breaks are made explicit (e.g., when break
    // is omitted for the final case statement).
    var previous = _inLabeledContinueSwitch;
    _inLabeledContinueSwitch = hasLabeledContinue(node);

    var cases = <js_ast.SwitchClause>[];

    if (_inLabeledContinueSwitch) {
      var labelState = _emitScopedId('labelState');
      // TODO(markzipan): Retrieve the real label name with source offsets
      var labelName = 'SL${_switchLabelStates.length}';
      _switchLabelStates[node] = _SwitchLabelState(labelName, labelState);

      // Since we wrap the switch in a 'while (true)' loop the continue targets
      // within the switch will no longer target the correct loop so we need
      // explicit breaks.
      final savedCurrentContinueTargets = _currentContinueTargets;
      _currentContinueTargets = [];

      for (var c in node.cases) {
        var subcases =
            _visitSwitchCase(c, lastSwitchCase: c == node.cases.last);
        if (subcases.isNotEmpty) cases.addAll(subcases);
      }
      _currentContinueTargets = savedCurrentContinueTargets;

      var switchExpr = _visitExpression(node.expression);
      var switchStmt = js_ast.Switch(labelState, cases);
      var loopBody = js_ast.Block([switchStmt, js_ast.Break(null)]);
      var loopStmt = js_ast.While(js.boolean(true), loopBody);
      // Note: Cannot use _labelNames, as the label must be on the loop.
      // not the block surrounding the switch statement.
      var labeledStmt = js_ast.LabeledStatement(labelName, loopStmt);
      var block = js_ast.Block([
        js.statement('let # = #', [labelState, switchExpr]),
        labeledStmt
      ]);
      _inLabeledContinueSwitch = previous;
      return block;
    }

    for (var c in node.cases) {
      var subcases = _visitSwitchCase(c);
      if (subcases.isNotEmpty) cases.addAll(subcases);
    }

    var stmt = js_ast.Switch(_visitExpression(node.expression), cases);
    _inLabeledContinueSwitch = previous;
    return stmt;
  }

  /// Helper for visiting a SwitchCase statement.
  ///
  /// [lastSwitchCase] is only used when the current switch statement contains
  /// labeled continues. Dart permits the final case to implicitly break, but
  /// switch statements with labeled continues must explicitly break/continue
  /// to escape the surrounding infinite loop.
  List<js_ast.SwitchClause> _visitSwitchCase(SwitchCase node,
      {bool lastSwitchCase = false}) {
    var cases = <js_ast.SwitchClause>[];
    var emptyBlock = js_ast.Block.empty();
    // TODO(jmesserly): make sure we are statically checking fall through
    var body = _visitStatement(node.body).toBlock();
    var expressions = node.expressions;
    var lastExpr =
        expressions.isNotEmpty && !node.isDefault ? expressions.last : null;
    for (var e in expressions) {
      var jsExpr = _visitExpression(e);
      if (e is ConstantExpression && e.constant is NullConstant) {
        // Coerce null and undefined by adding an extra case.
        cases.add(js_ast.Case(js_ast.Prefix('void', js.number(0)), emptyBlock));
      }
      cases.add(js_ast.Case(jsExpr, e == lastExpr ? body : emptyBlock));
    }
    if (node.isDefault) {
      cases.add(js_ast.Default(body));
    }
    // Switch statements with continue labels must explicitly break from their
    // last case to escape the additional loop around the switch.
    if (lastSwitchCase && _inLabeledContinueSwitch && cases.isNotEmpty) {
      // TODO(markzipan): avoid generating unreachable breaks
      var switchStmt = node.parent as SwitchStatement;
      assert(_switchLabelStates.containsKey(node.parent));
      var breakStmt = js_ast.Break(_switchLabelStates[switchStmt]!.label);
      var switchBody = js_ast.Block(cases.last.body.statements..add(breakStmt));
      var lastCase = cases.last;
      var updatedSwitch = lastCase is js_ast.Case
          ? js_ast.Case(lastCase.expression, switchBody)
          : js_ast.Default(switchBody);
      cases.removeLast();
      cases.add(updatedSwitch);
    }
    return cases;
  }

  @override
  js_ast.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
    var switchStmt = node.target.parent as SwitchStatement;
    if (_inLabeledContinueSwitch &&
        _switchLabelStates.containsKey(switchStmt)) {
      var switchState = _switchLabelStates[switchStmt]!;
      // Use the first constant expression that can match the collated switch
      // case. Use an unused symbol otherwise to force the default case.
      var jsExpr = node.target.expressions.isEmpty
          ? js.call("Symbol('_default')", [])
          : _visitExpression(node.target.expressions[0]);
      var setStateStmt = js.statement('# = #', [switchState.variable, jsExpr]);
      var continueStmt = js_ast.Continue(switchState.label);
      return js_ast.Block([setStateStmt, continueStmt]);
    }
    return _emitInvalidNode(
            node, 'see https://github.com/dart-lang/sdk/issues/29352')
        .toStatement();
  }

  @override
  js_ast.Statement visitIfStatement(IfStatement node) {
    bool isTriviallyTrue(condition) =>
        condition is js_ast.LiteralBool && condition.value;

    bool isTriviallyFalse(condition) =>
        condition is js_ast.LiteralBool && !condition.value;

    var condition = _visitTest(node.condition);
    if (isTriviallyTrue(condition)) return _visitScope(node.then);
    var otherwise = node.otherwise;
    var hasElse = otherwise != null;
    if (isTriviallyFalse(condition)) {
      return hasElse ? _visitScope(otherwise) : js_ast.EmptyStatement();
    }
    return hasElse
        ? js_ast.If(condition, _visitScope(node.then), _visitScope(otherwise))
        : js_ast.If.noElse(condition, _visitScope(node.then));
  }

  /// Visits a statement, and ensures the resulting AST handles block scope
  /// correctly. Essentially, we need to promote a variable declaration
  /// statement into a block in some cases, e.g.
  ///
  ///     do var x = 5; while (false); // Dart
  ///     do { let x = 5; } while (false); // JS
  js_ast.Statement _visitScope(Statement stmt) {
    var result = _visitStatement(stmt);
    if (result is js_ast.ExpressionStatement &&
        result.expression is js_ast.VariableDeclarationList) {
      return js_ast.Block([result]);
    }
    return result;
  }

  @override
  js_ast.Statement visitReturnStatement(ReturnStatement node) {
    var expression = node.expression;
    var value = expression == null ? null : _visitExpression(expression);
    return _emitReturnStatement(value);
  }

  @override
  js_ast.Statement visitTryCatch(TryCatch node) {
    return js_ast.Try(
        _visitStatement(node.body).toBlock(), _visitCatch(node.catches), null);
  }

  js_ast.Catch? _visitCatch(List<Catch> clauses) {
    if (clauses.isEmpty) return null;

    var caughtError = VariableDeclaration('#e', isSynthesized: true);
    var savedRethrow = _rethrowParameter;
    _rethrowParameter = caughtError;

    // If we have more than one catch clause, always create a temporary so we
    // don't shadow any names.
    var exceptionParameter =
        (clauses.length == 1 ? clauses[0].exception : null) ??
            VariableDeclaration('#ex', isSynthesized: true);

    var stackTraceParameter =
        (clauses.length == 1 ? clauses[0].stackTrace : null) ??
            (clauses.any((c) => c.stackTrace != null)
                ? VariableDeclaration('#st', isSynthesized: true)
                : null);

    js_ast.Statement catchBody = js_ast.Throw(_emitVariableRef(caughtError));
    for (var clause in clauses.reversed) {
      catchBody = _catchClauseGuard(
          clause, catchBody, exceptionParameter, stackTraceParameter);
    }
    var catchStatements = [
      js.statement('let # = #', [
        _emitVariableDef(exceptionParameter),
        _runtimeCall('getThrown(#)', [_emitVariableRef(caughtError)])
      ]),
      if (stackTraceParameter != null)
        js.statement('let # = #', [
          _emitVariableDef(stackTraceParameter),
          _runtimeCall('stackTrace(#)', [_emitVariableRef(caughtError)])
        ]),
      catchBody,
    ];
    _rethrowParameter = savedRethrow;
    return js_ast.Catch(_emitVariableDef(caughtError),
        js_ast.Block(catchStatements, isScope: true));
  }

  js_ast.Statement _catchClauseGuard(
      Catch node,
      js_ast.Statement otherwise,
      VariableDeclaration exceptionParameter,
      VariableDeclaration? stackTraceParameter) {
    var body = <js_ast.Statement>[];
    var vars = HashSet<String>();

    void declareVariable(
        VariableDeclaration? variable, VariableDeclaration? value) {
      if (variable == null || value == null) return;
      vars.add(variable.name!);
      if (variable.name != value.name) {
        body.add(js.statement('let # = #',
            [_emitVariableDef(variable), _emitVariableRef(value)]));
      }
    }

    declareVariable(node.exception, exceptionParameter);
    declareVariable(node.stackTrace, stackTraceParameter);

    body.add(_visitStatement(node.body).toScopedBlock(vars));
    // Each catch clause defines its own scope.
    var then = js_ast.Block(body, isScope: true);
    var guardType = node.guard.extensionTypeErasure;
    // Discard following clauses, if any, as they are unreachable.
    if (_types.isTop(guardType)) return then;

    var condition =
        _emitIsExpression(VariableGet(exceptionParameter), guardType);
    return js_ast.If(condition, then, otherwise)
      ..sourceInformation = _nodeStart(node);
  }

  @override
  js_ast.Statement visitTryFinally(TryFinally node) {
    var body = _visitStatement(node.body);
    var finallyBlock =
        _superDisallowed(() => _visitStatement(node.finalizer).toBlock());

    if (body is js_ast.Try && body.finallyPart == null) {
      // Kernel represents Dart try/catch/finally as try/catch nested inside of
      // try/finally.  Flatten that pattern in the output into JS try/catch/
      // finally.
      return js_ast.Try(body.body, body.catchPart, finallyBlock);
    }
    return js_ast.Try(body.toBlock(), null, finallyBlock);
  }

  @override
  js_ast.Statement visitYieldStatement(YieldStatement node) {
    return js_ast.DartYield(
        _visitExpression(node.expression), node.isYieldStar);
  }

  @override
  js_ast.Statement visitVariableDeclaration(VariableDeclaration node) {
    // TODO(jmesserly): casts are sometimes required here.
    // Kernel does not represent these explicitly.
    var v = _emitVariableDef(node);
    return js.statement('let # = #;',
        [v, _visitInitializer(node.initializer, node.annotations)]);
  }

  @override
  js_ast.Statement visitFunctionDeclaration(FunctionDeclaration node) {
    var func = node.function;
    var fn = _emitFunction(func, node.variable.name);

    var name = _emitVariableDef(node.variable);
    js_ast.Statement declareFn;
    declareFn = js_ast.toBoundFunctionStatement(fn, name);
    if (_reifyFunctionType(func)) {
      declareFn = js_ast.Block([
        declareFn,
        _emitFunctionTagged(_emitVariableRef(node.variable),
                func.computeThisFunctionType(_currentLibrary!.nonNullable))
            .toStatement()
      ]);
    }
    return declareFn;
  }

  @override
  js_ast.Expression visitInvalidExpression(InvalidExpression node) =>
      _emitInvalidNode(node);

  @override
  js_ast.Expression visitConstantExpression(ConstantExpression node) =>
      visitConstant(node.constant);

  @override
  js_ast.Expression visitVariableGet(VariableGet node) {
    var v = node.variable;
    var id = _emitVariableRef(v);
    if (id.name == v.name) {
      id = id.withSourceInformation(
          _variableSpan(node.fileOffset, v.name!.length));
    }
    return id;
  }

  /// Detects temporary variables so we can avoid displaying
  /// them in the debugger if needed.
  bool _isTemporaryVariable(VariableDeclaration v) {
    // Late local variables are be exposed to the debugger for inspection and
    // evaluation by treating the backing store local variable as a regular
    // non-temporary variable.
    // See https://github.com/dart-lang/sdk/issues/55918
    if (isLateLoweredLocal(v)) return false;
    return v.isLowered ||
        v.isSynthesized ||
        v.name == null ||
        v.name!.startsWith('#');
  }

  /// Creates a temporary name recognized by the debugger.
  /// Assumes `_isTemporaryVariable(v)`  is true.
  String? _debuggerFriendlyTemporaryVariableName(VariableDeclaration v) {
    assert(_isTemporaryVariable(v));

    // Show extension 'this' in the debugger.
    // Do not show the rest of temporary variables.
    if (isExtensionThis(v)) {
      return extractLocalNameFromVariable(v);
    } else if (v.name != null) {
      return 't\$${v.name}';
    }
    return null;
  }

  js_ast.ScopedId _emitVariableRef(VariableDeclaration v) {
    if (_isTemporaryVariable(v)) {
      var name = _debuggerFriendlyTemporaryVariableName(v);
      name ??= 't\$${_tempVariables.length}';
      return _tempVariables.putIfAbsent(v, () => _emitScopedId(name!));
    }
    var name = v.name!;
    if (isLateLoweredLocal(v)) {
      // Late local variables are be exposed to the debugger for inspection and
      // evaluation by treating the backing store local variable as a regular
      // non-temporary variable.
      // See https://github.com/dart-lang/sdk/issues/55918
      name = extractLocalNameFromLateLoweredLocal(name);
    }
    return js_ast.ScopedId.from(
        _variableTempIds[v] ??= _emitScopedId(name, needsCapture: true));
  }

  /// Emits the declaration of a variable.
  ///
  /// This is similar to [_emitVariableRef] but it also attaches source
  /// location information, so hover will work as expected.
  js_ast.Identifier _emitVariableDef(VariableDeclaration v) {
    var identifier = _emitVariableRef(v)..sourceInformation = _nodeStart(v);
    variableIdentifiers[v] = identifier;
    return identifier;
  }

  js_ast.Statement? _initLetVariables() {
    var letVars = _letVariables!;
    if (letVars.isEmpty) return null;
    var result = js_ast.VariableDeclarationList('let',
            letVars.map((v) => js_ast.VariableInitialization(v, null)).toList())
        .toStatement();
    letVars.clear();
    return result;
  }

  // TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
  @override
  js_ast.Expression visitVariableSet(VariableSet node) {
    // Make the source information of the assignment use the start of the right
    // hand side, to help normalize the inconsistent locations of the CFE
    // lowerings for ++x, x++, x+=, etc.
    // See https://github.com/dart-lang/sdk/issues/55691.
    return _visitExpression(node.value)
        .toAssignExpression(_emitVariableRef(node.variable))
      ..sourceInformation = _nodeStart(node.value);
  }

  @override
  js_ast.Expression visitDynamicGet(DynamicGet node) {
    var jsReceiver = _visitExpression(node.receiver);
    var jsMemberName = _emitMemberName(node.name.text);
    return _runtimeCall('dload$_replSuffix(#, #)', [jsReceiver, jsMemberName]);
  }

  @override
  js_ast.Expression visitInstanceGet(InstanceGet node) {
    // TODO(nshahan): Marking an end span for property accessors would improve
    // source maps and hovering in the debugger. Unfortunately this is not
    // possible as Kernel does not store this data.
    var member = node.interfaceTarget;
    var receiver = node.receiver;
    var jsReceiver = _visitExpression(receiver);
    if (_isNonStaticJsInteropCallMember(member)) {
      // Historically DDC has treated this as a "callable class" and the access
      // of `.call` as a no-op.
      //
      // This is here to preserve the existing behavior for the non-static
      // JavaScript interop (including some failing cases) but could potentially
      // be cleaned up as a breaking change.
      return jsReceiver;
    }
    var memberName = node.name.text;
    if (_isObjectGetter(memberName) &&
        _shouldCallObjectMemberHelper(receiver)) {
      // The names of the static helper methods in the runtime must match the
      // names of the Object instance getters.
      return _runtimeCall('#(#)', [memberName, jsReceiver]);
    }
    // Otherwise generate this as a normal typed property get.
    var jsMemberName =
        _emitMemberName(memberName, member: node.interfaceTarget);
    var instanceGet = js_ast.PropertyAccess(jsReceiver, jsMemberName);
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(instanceGet)
        : instanceGet;
  }

  @override
  js_ast.Expression visitRecordIndexGet(RecordIndexGet node) =>
      _emitRecordElementGet(node.receiver, '\$${node.index + 1}');

  @override
  js_ast.Expression visitRecordNameGet(RecordNameGet node) =>
      _emitRecordElementGet(node.receiver, node.name);

  js_ast.Expression _emitRecordElementGet(
          Expression receiver, String elementName) =>
      js_ast.PropertyAccess(
          _visitExpression(receiver), _emitMemberName(elementName));

  @override
  js_ast.Expression visitInstanceTearOff(InstanceTearOff node) {
    var member = node.interfaceTarget;
    var receiver = node.receiver;
    var jsReceiver = _visitExpression(receiver);
    if (_isNonStaticJsInteropCallMember(member)) {
      // Historically DDC has treated this as a "callable class" and the tearoff
      // of `.call` as a no-op.
      //
      // This is here to preserve the existing behavior for the non-static
      // JavaScript interop (including some failing cases) but could potentially
      // be cleaned up as a breaking change.
      return jsReceiver;
    }
    var memberName = node.name.text;
    if (_isObjectMethodTearoff(memberName) &&
        _shouldCallObjectMemberHelper(receiver)) {
      // The names of the static helper methods in the runtime must start with
      // the names of the Object instance methods.
      var tearOffName = '${memberName}Tearoff';
      return _runtimeCall('#(#)', [tearOffName, jsReceiver]);
    }
    var jsMemberName = _emitMemberName(memberName, member: member);
    if (_reifyTearoff(member)) {
      return _runtimeCall('bind(#, #)', [jsReceiver, jsMemberName]);
    }
    var jsPropertyAccess = js_ast.PropertyAccess(jsReceiver, jsMemberName);
    return isJsMember(member)
        ? _runtimeCall('tearoffInterop(#, #)',
            [jsPropertyAccess, js.boolean(_isNullCheckableJsInterop(member))])
        : jsPropertyAccess;
  }

  /// Returns `true` when [member] is a `.call` member (field, getter or method)
  /// of a non-static JavaScript interop class.
  bool _isNonStaticJsInteropCallMember(Member member) =>
      member.name.text == 'call' && isNonStaticJsInterop(member);

  @override
  js_ast.Expression visitDynamicSet(DynamicSet node) {
    return _emitPropertySet(node.receiver, null, node.value, node.name.text);
  }

  @override
  js_ast.Expression visitInstanceSet(InstanceSet node) {
    return _emitPropertySet(
        node.receiver, node.interfaceTarget, node.value, node.name.text);
  }

  /// True when the result of evaluating [e] is not known to have the Object
  /// members installed so a helper method should be called instead of a direct
  /// instance invocation.
  ///
  /// This is a best effort approach determined by the static type information
  /// and may return `true` when the evaluation result does in fact have the
  /// members at runtime.
  bool _shouldCallObjectMemberHelper(Expression e) {
    if (_isNullable(e)) return true;
    var type = e.getStaticType(_staticTypeContext).extensionTypeErasure;
    if (type is RecordType || type is FunctionType) return false;
    if (type is InterfaceType) {
      // TODO(nshahan): This could be expanded to any classes where we know all
      // implementations at compile time and none of them are JS interop.
      var cls = type.classNode;
      // NOTE: This is not guaranteed to always be true. Currently in the SDK
      // none of the final classes or their subtypes use JavaScript interop.
      // If that was to ever change, this check will need to be updated.
      // For now, this is a shortcut since all subclasses of a class are not
      // immediately accessible.
      if (cls.isFinal && cls.enclosingLibrary.importUri.isScheme('dart')) {
        return false;
      }
    }
    // Constants have a static type known at compile time that will not be a
    // subtype at runtime.
    return !_triviallyConstNoInterop(e);
  }

  /// True when [e] is known to evaluate to a constant that has an interface
  /// type that is not a JavaScript interop type.
  ///
  /// This is a simple approach and not an exhaustive search.
  bool _triviallyConstNoInterop(Expression? e) {
    if (e is ConstantExpression) {
      var type = e.constant.getType(_staticTypeContext).extensionTypeErasure;
      if (type is InterfaceType) return !usesJSInterop(type.classNode);
    } else if (e is StaticGet && e.target.isConst) {
      var target = e.target;
      if (target is Field) {
        return _triviallyConstNoInterop(target.initializer);
      }
    } else if (e is VariableGet && e.variable.isConst) {
      return _triviallyConstNoInterop(e.variable.initializer);
    }
    return false;
  }

  /// Returns [expression] wrapped in an optional null check.
  ///
  /// The null check is enabled by setting a flag during the application
  /// bootstrap via `jsInteropNonNullAsserts(true)` in the SDK runtime library.
  js_ast.Expression _wrapWithJsInteropNullCheck(js_ast.Expression expression) =>
      _runtimeCall('jsInteropNullCheck(#)', [expression]);

  /// Returns `true` when [member] is a JavaScript interop API that should be
  /// checked to be not null when the runtime flag `--interop-null-assertions`
  /// is enabled.
  ///
  /// These APIs are defined using the non-static package:js interop library and
  /// are typed to be non-nullable.
  bool _isNullCheckableJsInterop(Member member) {
    var type =
        member is Procedure ? member.function.returnType : member.getterType;
    return type.nullability == Nullability.nonNullable &&
        isNonStaticJsInterop(member);
  }

  /// Return whether [member] returns a native object whose type needs to be
  /// null-checked in sound null-safety.
  ///
  /// This is true for non-nullable native return types.
  bool _isNullCheckableNative(Member member) {
    var c = member.enclosingClass;
    return _options.soundNullSafety &&
        member.isExternal &&
        c != null &&
        _extensionTypes.isNativeClass(c) &&
        member is Procedure &&
        member.function.returnType.isPotentiallyNonNullable &&
        _isWebLibrary(member.enclosingLibrary.importUri);
  }

  // TODO(jmesserly): can we encapsulate REPL name lookups and remove this?
  // _emitMemberName would be a nice place to handle it, but we don't have
  // access to the target expression there (needed for `dart.replNameLookup`).
  String get _replSuffix => _options.replCompile ? 'Repl' : '';

  js_ast.Expression _emitPropertySet(Expression receiver, Member? member,
      Expression value, String memberName) {
    var jsName = _emitMemberName(memberName, member: member);

    if (member != null && isJsMember(member)) {
      value = _assertInterop(value);
    }

    var jsReceiver = _visitExpression(receiver);
    var jsValue = _visitExpression(value);

    if (member == null) {
      return _runtimeCall(
          'dput$_replSuffix(#, #, #)', [jsReceiver, jsName, jsValue]);
    }
    return js.call('#.# = #', [jsReceiver, jsName, jsValue]);
  }

  @override
  js_ast.Expression visitAbstractSuperPropertyGet(
      AbstractSuperPropertyGet node) {
    return _emitSuperPropertyGet(node.interfaceTarget);
  }

  @override
  js_ast.Expression visitSuperPropertyGet(SuperPropertyGet node) {
    return _emitSuperPropertyGet(node.interfaceTarget);
  }

  js_ast.Expression _emitSuperPropertyGet(Member target) {
    if (_reifyTearoff(target)) {
      if (_superAllowed) {
        var jsTarget = _emitSuperTarget(target);
        return _runtimeCall('bind(this, #, #)', [jsTarget.selector, jsTarget]);
      } else {
        return _emitSuperTearoff(target);
      }
    }
    return _emitSuperTarget(target);
  }

  @override
  js_ast.Expression visitAbstractSuperPropertySet(
      AbstractSuperPropertySet node) {
    return _emitSuperPropertySet(node.interfaceTarget, node.value);
  }

  @override
  js_ast.Expression visitSuperPropertySet(SuperPropertySet node) {
    return _emitSuperPropertySet(node.interfaceTarget, node.value);
  }

  js_ast.Expression _emitSuperPropertySet(Member target, Expression value) {
    var jsTarget = _emitSuperTarget(target, setter: true);
    return _visitExpression(value).toAssignExpression(jsTarget);
  }

  @override
  js_ast.Expression visitStaticGet(StaticGet node) {
    final target = node.target;
    if (_isDartJsHelper(target.enclosingLibrary)) {
      final name = target.name.text;
      if (name == 'staticInteropGlobalContext') {
        return _runtimeCall('global');
      }
    }
    var staticGet = _emitStaticGet(target);
    return _isNullCheckableJsInterop(target)
        ? _wrapWithJsInteropNullCheck(staticGet)
        : staticGet;
  }

  @override
  js_ast.Expression visitStaticTearOff(StaticTearOff node) =>
      _emitStaticGet(node.target);

  js_ast.Expression _emitStaticGet(Member target) {
    var result = _emitStaticTarget(target);
    if (_reifyTearoff(target)) {
      // TODO(jmesserly): we could tag static/top-level function types once
      // in the module initialization, rather than at the point where they
      // escape.
      return _emitFunctionTagged(
          result,
          target.function!
              .computeThisFunctionType(target.enclosingLibrary.nonNullable));
    }
    return result;
  }

  @override
  js_ast.Expression visitStaticSet(StaticSet node) {
    var target = node.target;
    var result = _emitStaticTarget(target);
    var value = isJsMember(target) ? _assertInterop(node.value) : node.value;
    return _visitExpression(value).toAssignExpression(result);
  }

  @override
  js_ast.Expression visitDynamicInvocation(DynamicInvocation node) {
    return _emitMethodCall(node.receiver, null, node.arguments, node);
  }

  @override
  js_ast.Expression visitFunctionInvocation(FunctionInvocation node) {
    return _emitMethodCall(node.receiver, null, node.arguments, node);
  }

  @override
  js_ast.Expression visitInstanceInvocation(InstanceInvocation node) {
    var invocation = _emitMethodCall(
        node.receiver, node.interfaceTarget, node.arguments, node);
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(invocation)
        : invocation;
  }

  @override
  js_ast.Expression visitInstanceGetterInvocation(
      InstanceGetterInvocation node) {
    var getterInvocation = _emitMethodCall(
        node.receiver, node.interfaceTarget, node.arguments, node);
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(getterInvocation)
        : getterInvocation;
  }

  @override
  js_ast.Expression visitLocalFunctionInvocation(LocalFunctionInvocation node) {
    return _emitMethodCall(
        VariableGet(node.variable)..fileOffset = node.fileOffset,
        null,
        node.arguments,
        node);
  }

  @override
  js_ast.Expression visitEqualsCall(EqualsCall node) {
    return _emitEqualityOperator(node.left, node.interfaceTarget, node.right,
        negated: false);
  }

  @override
  js_ast.Expression visitEqualsNull(EqualsNull node) {
    return _emitCoreIdenticalCall([node.expression, NullLiteral()],
        negated: false);
  }

  js_ast.Expression _emitMethodCall(Expression receiver, Member? target,
      Arguments arguments, InvocationExpression node) {
    var name = node.name.text;

    /// Returns `true` when [node] represents an invocation of `List.add()` that
    /// can be optimized.
    ///
    /// The optimized add operation can skip checks for a growable or modifiable
    /// list and the element type is known to be invariant so it can skip the
    /// type check.
    bool isNativeListInvariantAdd(InvocationExpression node) {
      if (node is InstanceInvocation &&
          node.isInvariant &&
          node.name.text == 'add') {
        // The call to add is marked as invariant, so the type check on the
        // parameter to add is not needed.
        var receiver = node.receiver;
        if (receiver is VariableGet &&
            receiver.variable.isFinal &&
            !receiver.variable.isLate) {
          // The receiver is a final variable, so it only contains the
          // initializer value. Also, avoid late variables in case the CFE
          // lowering of late variables is changed in the future.
          var initializer = receiver.variable.initializer;
          if (initializer is ListLiteral) {
            // The initializer is a list literal, so we know the list can be
            // grown, modified, and is represented by a JavaScript Array.
            return true;
          }
          if (initializer is StaticInvocation &&
              initializer.target.enclosingClass == _coreTypes.listClass &&
              initializer.target.name.text == 'of' &&
              initializer.arguments.named.isEmpty) {
            // The initializer is a `List.of()` call from the dart:core library
            // and the growable named argument has not been passed (it defaults
            // to true).
            return true;
          }
        }
      }
      return false;
    }

    if (isOperatorMethodName(name) && arguments.named.isEmpty) {
      var argLength = arguments.positional.length;
      if (argLength == 0) {
        return _emitUnaryOperator(receiver, target, node);
      } else if (argLength == 1) {
        return _emitBinaryOperator(
            receiver, target, arguments.positional[0], node);
      }
    }

    var jsReceiver = _visitExpression(receiver);
    var args = _emitArgumentList(arguments, target: target);

    if (isNativeListInvariantAdd(node)) {
      return js.call('#.push(#)', [jsReceiver, args]);
    }

    var isCallingDynamicField = target is Member &&
        target.hasGetter &&
        // Erasing extension types here doesn't make sense. If there is an
        // extension type on dynamic or Function it will only be callable if it
        // defines a call method which would be invoked statically.
        _isDynamicOrFunction(target.getterType);
    if (name == 'call') {
      // Erasing the extension types here to support existing callable behaivor
      // on the old style JS interop types that are callable. This should be
      // safe as it is a compile time error to try to dynamically invoke a call
      // method that is inherited from an extension type.
      var receiverType =
          receiver.getStaticType(_staticTypeContext).extensionTypeErasure;
      if (isCallingDynamicField || _isDynamicOrFunction(receiverType)) {
        return _emitDynamicInvoke(jsReceiver, null, args, arguments);
      } else if (_isDirectCallable(receiverType)) {
        // Call methods on function types should be handled as function calls.
        return js_ast.Call(jsReceiver, args);
      }
    }

    var jsName = _emitMemberName(name, member: target);

    // Handle Object methods that are supported by `null` and potentially
    // JavaScript interop values.
    if (_isObjectMethodCall(name, arguments)) {
      if (_shouldCallObjectMemberHelper(receiver)) {
        // The names of the static helper methods in the runtime must match the
        // names of the Object instance members.
        return _runtimeCall('#(#, #)', [name, jsReceiver, args]);
      }
      // Otherwise generate this as a normal typed method call.
    } else if (target == null || isCallingDynamicField) {
      return _emitDynamicInvoke(jsReceiver, jsName, args, arguments);
    }
    // TODO(jmesserly): remove when Kernel desugars this for us.
    // Handle `o.m(a)` where `o.m` is a getter returning a class with `call`.
    if (target is Field || target is Procedure && target.isAccessor) {
      // We must erase the extension type to find the `call` method.
      // If the extension type has a runtime representation with a `call`:
      //
      // ```
      // extension type Ext(C c) implements C {...}
      // class C {
      //   call() {...}
      // }
      // ```
      //
      // We can always erase eagerly becuase:
      //  - Extension types that do not implment an interface that exposes a
      //    `call` method will result in a static error at the call site.
      //  - Calls to extension types that implement their own call method are
      //    lowered by the CFE to top level static method calls.
      var fromType = target!.getterType.extensionTypeErasure;
      if (fromType is InterfaceType) {
        var callName = _implicitCallTarget(fromType);
        if (callName != null) {
          return js.call('#.#.#(#)', [jsReceiver, jsName, callName, args]);
        }
      }
    }
    return js.call('#.#(#)', [jsReceiver, jsName, args]);
  }

  js_ast.Expression _emitDynamicInvoke(
      js_ast.Expression fn,
      js_ast.Expression? methodName,
      Iterable<js_ast.Expression> args,
      Arguments arguments) {
    var jsArgs = <Object>[fn];
    String jsCode;

    var typeArgs = arguments.types;
    if (typeArgs.isNotEmpty) {
      jsArgs.add(args.take(typeArgs.length));
      args = args.skip(typeArgs.length);
      if (methodName != null) {
        jsCode = 'dgsend$_replSuffix(#, [#], #';
        jsArgs.add(methodName);
      } else {
        jsCode = 'dgcall(#, [#]';
      }
    } else if (methodName != null) {
      jsCode = 'dsend$_replSuffix(#, #';
      jsArgs.add(methodName);
    } else {
      jsCode = 'dcall(#';
    }

    var hasNamed = arguments.named.isNotEmpty;
    if (hasNamed) {
      jsCode += ', [#], #)';
      jsArgs.add(args.take(args.length - 1));
      jsArgs.add(args.last);
    } else {
      jsArgs.add(args);
      jsCode += ', [#])';
    }

    return _runtimeCall(jsCode, jsArgs);
  }

  bool _isDirectCallable(DartType t) =>
      t is FunctionType || (t is InterfaceType && usesJSInterop(t.classNode));

  js_ast.Expression? _implicitCallTarget(InterfaceType from) {
    var c = from.classNode;
    var member = _hierarchy.getInterfaceMember(c, Name('call'));
    if (member is Procedure && !member.isAccessor && !usesJSInterop(c)) {
      return _emitMemberName('call', member: member);
    }
    return null;
  }

  bool _isDynamicOrFunction(DartType t) =>
      DartTypeEquivalence(_coreTypes, ignoreTopLevelNullability: true)
          .areEqual(t, _coreTypes.functionNonNullableRawType) ||
      t == const DynamicType();

  js_ast.Expression _emitUnaryOperator(
      Expression expr, Member? target, InvocationExpression node) {
    var op = node.name.text;
    if (target != null) {
      var dispatchType = _coreTypes.nonNullableRawType(target.enclosingClass!);
      if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
        if (op == '~') {
          if (_typeRep.isNumber(dispatchType)) {
            return _coerceBitOperationResultToUnsigned(
                node, js.call('~#', _notNull(expr)));
          }
          return _emitOperatorCall(expr, target, op, []);
        }
        if (op == 'unary-') op = '-';
        return js.call('$op#', _notNull(expr));
      }
    }
    return _emitOperatorCall(expr, target, op, []);
  }

  /// Bit operations are coerced to values on [0, 2^32). The coercion changes
  /// the interpretation of the 32-bit value from signed to unsigned.  Most
  /// JavaScript operations interpret their operands as signed and generate
  /// signed results.
  js_ast.Expression _coerceBitOperationResultToUnsigned(
      Expression node, js_ast.Expression uncoerced) {
    // Don't coerce if the parent will coerce.
    var parent = node.parent;
    if (parent is InvocationExpression && _nodeIsBitwiseOperation(parent)) {
      return uncoerced;
    }

    // Don't do a no-op coerce if the most significant bit is zero.
    if (_is31BitUnsigned(node)) return uncoerced;

    // If the consumer of the expression is '==' or '!=' with a constant that
    // fits in 31 bits, adding a coercion does not change the result of the
    // comparison, e.g.  `a & ~b == 0`.
    Expression? left;
    late Expression right;
    late String op;
    if (parent is InvocationExpression &&
        parent.arguments.positional.length == 1) {
      op = parent.name.text;
      left = getInvocationReceiver(parent);
      right = parent.arguments.positional[0];
    } else if (parent is EqualsCall) {
      left = parent.left;
      right = parent.right;
      op = '==';
    } else if (parent is EqualsNull) {
      left = parent.expression;
      right = NullLiteral();
      op = '==';
    }
    if (left != null) {
      if (op == '==') {
        const MAX = 0x7fffffff;
        if (_asIntInRange(right, 0, MAX) != null) return uncoerced;
        if (_asIntInRange(left, 0, MAX) != null) return uncoerced;
      } else if (op == '>>') {
        if (_isDefinitelyNonNegative(left) &&
            _asIntInRange(right, 0, 31) != null) {
          // Parent will generate `# >>> n`.
          return uncoerced;
        }
      }
    }
    return js.call('# >>> 0', uncoerced);
  }

  bool _nodeIsBitwiseOperation(InvocationExpression node) {
    switch (node.name.text) {
      case '&':
      case '|':
      case '^':
      case '~':
        return true;
    }
    return false;
  }

  int? _asIntInRange(Expression expr, int low, int high) {
    if (expr is IntLiteral) {
      if (expr.value >= low && expr.value <= high) return expr.value;
      return null;
    }
    if (_constants.isConstant(expr)) {
      var c = _constants.evaluate(expr);
      if (c is IntConstant && c.value >= low && c.value <= high) return c.value;
    }
    return null;
  }

  bool _isDefinitelyNonNegative(Expression expr) {
    if (expr is IntLiteral) return expr.value >= 0;

    // TODO(sra): Lengths of known list types etc.
    return expr is InvocationExpression && _nodeIsBitwiseOperation(expr);
  }

  /// Does the parent of [node] mask the result to [width] bits or fewer?
  bool _parentMasksToWidth(Expression node, int width) {
    var parent = node.parent;
    if (parent == null) return false;
    if (parent is InvocationExpression && _nodeIsBitwiseOperation(parent)) {
      if (parent.name.text == '&' && parent.arguments.positional.length == 1) {
        var left = getInvocationReceiver(parent);
        var right = parent.arguments.positional[0];
        final max = (1 << width) - 1;
        if (left != null) {
          if (_asIntInRange(right, 0, max) != null) return true;
          if (_asIntInRange(left, 0, max) != null) return true;
        }
      }
      return _parentMasksToWidth(parent, width);
    }
    return false;
  }

  /// Determines if the result of evaluating [expr] will be an non-negative
  /// value that fits in 31 bits.
  bool _is31BitUnsigned(Expression expr) {
    const MAX = 32; // Includes larger and negative values.
    /// Determines how many bits are required to hold result of evaluation
    /// [expr].  [depth] is used to bound exploration of huge expressions.
    int bitWidth(Expression expr, int depth) {
      if (expr is IntLiteral) {
        return expr.value >= 0 ? expr.value.bitLength : MAX;
      }
      if (++depth > 5) return MAX;
      if (expr is InvocationExpression &&
          expr.arguments.positional.length == 1) {
        var left = getInvocationReceiver(expr);
        var right = expr.arguments.positional[0];
        if (left != null) {
          switch (expr.name.text) {
            case '&':
              return min(bitWidth(left, depth), bitWidth(right, depth));

            case '|':
            case '^':
              return max(bitWidth(left, depth), bitWidth(right, depth));

            case '>>':
              var shiftValue = _asIntInRange(right, 0, 31);
              if (shiftValue != null) {
                var leftWidth = bitWidth(left, depth);
                return leftWidth == MAX ? MAX : max(0, leftWidth - shiftValue);
              }
              return MAX;

            case '<<':
              var leftWidth = bitWidth(left, depth);
              var shiftValue = _asIntInRange(right, 0, 31);
              if (shiftValue != null) {
                return min(MAX, leftWidth + shiftValue);
              }
              var rightWidth = bitWidth(right, depth);
              if (rightWidth <= 5) {
                // e.g.  `1 << (x & 7)` has a rightWidth of 3, so shifts by up to
                // (1 << 3) - 1 == 7 bits.
                return min(MAX, leftWidth + ((1 << rightWidth) - 1));
              }
              return MAX;
            default:
              return MAX;
          }
        }
      }
      var value = _asIntInRange(expr, 0, 0x7fffffff);
      if (value != null) return value.bitLength;
      return MAX;
    }

    return bitWidth(expr, 0) < 32;
  }

  js_ast.Expression _emitBinaryOperator(Expression left, Member? target,
      Expression right, InvocationExpression node) {
    var op = node.name.text;
    if (op == '==') return _emitEqualityOperator(left, target, right);

    // TODO(jmesserly): using the target type here to work around:
    // https://github.com/dart-lang/sdk/issues/33293
    if (target != null) {
      var targetClass = target.enclosingClass!;
      var leftType = _coreTypes.nonNullableRawType(targetClass);
      var rightType = right.getStaticType(_staticTypeContext);

      if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
          targetClass == _coreTypes.stringClass && op == '+') {
        // Inline operations on primitive types where possible.
        // TODO(jmesserly): inline these from dart:core instead of hardcoding
        // the implementation details here.

        /// Emits an inlined binary operation using the JS [code], adding null
        /// checks if needed to ensure we throw the appropriate error.
        js_ast.Expression binary(String code) {
          return js.call(code, [_notNull(left), _notNull(right)])
            ..sourceInformation = continueSourceMap;
        }

        js_ast.Expression bitwise(String code) {
          return _coerceBitOperationResultToUnsigned(node, binary(code));
        }

        /// Similar to [binary] but applies a boolean conversion to the right
        /// operand, to match the boolean bitwise operators in dart:core.
        ///
        /// Short circuiting operators should not be used in [code], because the
        /// null checks for both operands must happen unconditionally.
        js_ast.Expression bitwiseBool(String code) {
          return js.call(code, [_notNull(left), _visitTest(right)]);
        }

        switch (op) {
          case '~/':
            // `a ~/ b` is equivalent to `(a / b).truncate()`
            return js.call('(# / #).#()', [
              _notNull(left),
              _notNull(right),
              _emitMemberName('truncate', memberClass: targetClass)
            ]);

          case '%':
            // TODO(sra): We can generate `a % b + 0` if both are non-negative
            // (the `+ 0` is to coerce -0.0 to 0).
            return _emitOperatorCall(left, target, op, [right]);

          case '&':
            return _typeRep.isBoolean(leftType)
                ? bitwiseBool('!!(# & #)')
                : bitwise('# & #');

          case '|':
            return _typeRep.isBoolean(leftType)
                ? bitwiseBool('!!(# | #)')
                : bitwise('# | #');

          case '^':
            return _typeRep.isBoolean(leftType)
                ? bitwiseBool('# !== #')
                : bitwise('# ^ #');

          case '>>':
            var shiftCount = _asIntInRange(right, 0, 31);
            if (_is31BitUnsigned(left) && shiftCount != null) {
              return binary('# >> #');
            }
            if (_isDefinitelyNonNegative(left) && shiftCount != null) {
              return binary('# >>> #');
            }
            // If the context selects out only bits that can't be affected by the
            // sign position we can use any JavaScript shift, `(x >> 6) & 3`.
            if (shiftCount != null &&
                _parentMasksToWidth(node, 31 - shiftCount)) {
              return binary('# >> #');
            }
            return _emitOperatorCall(left, target, op, [right]);

          case '<<':
            if (_is31BitUnsigned(node)) {
              // Result is 31 bit unsigned which implies the shift count was small
              // enough not to pollute the sign bit.
              return binary('# << #');
            }
            if (_asIntInRange(right, 0, 31) != null) {
              return _coerceBitOperationResultToUnsigned(
                  node, binary('# << #'));
            }
            return _emitOperatorCall(left, target, op, [right]);

          case '>>>':
            if (_asIntInRange(right, 0, 31) != null) {
              return binary('# >>> #');
            }
            return _emitOperatorCall(left, target, op, [right]);

          default:
            // TODO(vsm): When do Dart ops not map to JS?
            return binary('# $op #');
        }
      }
    }

    return _emitOperatorCall(left, target, op, [right]);
  }

  js_ast.Expression _emitEqualityOperator(
      Expression left, Member? target, Expression right,
      {bool negated = false}) {
    var targetClass = target?.enclosingClass;
    var leftType = left.getStaticType(_staticTypeContext).extensionTypeErasure;

    // Conceptually `x == y` in Dart is defined as:
    //
    // If either x or y is null, then they are equal iff they are both null.
    // Otherwise, equality is the result of calling `x.==(y)`.
    //
    // In practice, `x.==(y)` is equivalent to `identical(x, y)` in many cases:
    // - when either side is known to be `null` (literal or Null type)
    // - left side is an enum
    // - left side is a primitive type
    //
    // We also compile `operator ==` methods to ensure they check the right side
    // for null`. This allows us to skip the check at call sites.
    //
    // TODO(leafp,jmesserly): we could use class hierarchy analysis to check
    // if `operator ==` was overridden, similar to how we devirtualize private
    // fields.
    //
    // If we know that the left type uses identity for equality, we can
    // sometimes emit better code, either `===` or `==`.
    var isEnum = leftType is InterfaceType && leftType.classNode.isEnum;

    var usesIdentity = _typeRep.isPrimitive(leftType) ||
        isEnum ||
        _isNull(left) ||
        _isNull(right);

    if (usesIdentity) {
      return _emitCoreIdenticalCall([left, right], negated: negated);
    }

    if (_shouldCallObjectMemberHelper(left)) {
      // The LHS isn't guaranteed to have an equals method we need to use a
      // runtime helper.
      return js.call(negated ? '!#' : '#', [
        _runtimeCall(
            'equals(#, #)', [_visitExpression(left), _visitExpression(right)])
      ]);
    }
    // Otherwise it is safe to call the equals method on the LHS directly.
    return js.call(negated ? '!#[#](#)' : '#[#](#)', [
      _visitExpression(left),
      _emitMemberName('==', memberClass: targetClass),
      _visitExpression(right)
    ]);
  }

  /// Emits a generic send, like an operator method.
  ///
  /// **Please note** this function does not support method invocation syntax
  /// `obj.name(args)` because that could be a getter followed by a call.
  /// See [visitMethodInvocation].
  js_ast.Expression _emitOperatorCall(
      Expression receiver, Member? target, String name, List<Expression> args) {
    // TODO(jmesserly): calls that don't pass `element` are probably broken for
    // `super` calls from disallowed super locations.
    var memberName = _emitMemberName(name, member: target);
    if (target == null) {
      // dynamic dispatch
      var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
      if (dynamicHelper != null) {
        return _runtimeCall('$dynamicHelper(#, #)',
            [_visitExpression(receiver), _visitExpressionList(args)]);
      } else {
        return _runtimeCall('dsend(#, #, [#])', [
          _visitExpression(receiver),
          memberName,
          _visitExpressionList(args)
        ]);
      }
    }

    // Generic dispatch to a statically known method.
    return js.call('#.#(#)',
        [_visitExpression(receiver), memberName, _visitExpressionList(args)]);
  }

  // TODO(jmesserly): optimize super operators for kernel
  @override
  js_ast.Expression visitAbstractSuperMethodInvocation(
      AbstractSuperMethodInvocation node) {
    return _emitSuperMethodInvocation(node.interfaceTarget, node.arguments);
  }

  @override
  js_ast.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
    return _emitSuperMethodInvocation(node.interfaceTarget, node.arguments);
  }

  js_ast.Expression _emitSuperMethodInvocation(
      Member target, Arguments arguments) {
    return js_ast.Call(
        _emitSuperTarget(target), _emitArgumentList(arguments, target: target));
  }

  /// Emits the [js_ast.PropertyAccess] for accessors or method calls to
  /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
  js_ast.PropertyAccess _emitSuperTarget(Member member, {bool setter = false}) {
    var jsName = _emitMemberName(member.name.text, member: member);
    // Optimize access to non-virtual fields, if allowed in the current context.
    if (_optimizeNonVirtualFieldAccess &&
        member is Field &&
        !_virtualFields.isVirtual(member)) {
      return js_ast.PropertyAccess(js_ast.This(), jsName);
    }
    if (_superAllowed) return js_ast.PropertyAccess(js_ast.Super(), jsName);

    // If we can't emit `super` in this context, generate a helper that does it
    // for us, and call the helper.
    //
    // NOTE: This is intended to help in the cases of calling a `super` getter,
    // setter, or method. For the case of tearing off a `super` method in
    // contexts where `super` isn't allowed, see [_emitSuperTearoff].
    var name = member.name.text;
    var getter = (member is Field && !setter) ||
        (member is Procedure && member.isGetter);
    // Prefix applied to the name only used in the compiler for a map key. This
    // name does not make its way into the compiled program.
    var lookupPrefix = setter
        ? r'set$'
        : getter
            ? r'get$'
            : '';
    var jsMethod = _superHelpers.putIfAbsent('$lookupPrefix$name', () {
      var isAccessor = member is Procedure ? member.isAccessor : true;
      if (isAccessor) {
        assert(member is Procedure
            ? member.isSetter == setter
            : !setter || !(member as Field).isFinal);
        var fn = js.fun(
            setter
                ? 'function(x) { super[#] = x; }'
                : 'function() { return super[#]; }',
            [jsName]);

        return js_ast.Method(_emitScopedId(name), fn,
            isGetter: !setter, isSetter: setter);
      } else {
        var function = member.function;
        var params = [
          ..._emitTypeFormals(function.typeParameters),
          for (var param in function.positionalParameters)
            _emitIdentifier(param.name!),
          if (function.namedParameters.isNotEmpty) _namedArgumentTemp,
        ];

        var fn = js.fun(
            'function(#) { return super[#](#); }', [params, jsName, params]);
        name = js_ast.friendlyNameForDartOperator[name] ?? name;
        return js_ast.Method(_emitScopedId(name), fn);
      }
    });
    return js_ast.PropertyAccess(js_ast.This(), jsMethod.name);
  }

  /// Generates a helper method that is inserted into the class that binds a
  /// tearoff of [member] from `super` and returns a call to the helper.
  ///
  /// This method assumes `super` is not allowed in the current context.
  // TODO(nshahan) Replace with a kernel transform and synthetic method filters
  // for devtools.
  js_ast.Expression _emitSuperTearoff(Member member) {
    var jsName = _emitMemberName(member.name.text, member: member);
    var name = '_#super#tearOff#${member.name.text}';
    var jsMethod = _superHelpers.putIfAbsent(name, () {
      var jsReturnValue =
          _runtimeCall('bind(this, #, super[#])', [jsName, jsName]);
      var fn = js.fun('function() { return #; }', [jsReturnValue]);
      name = js_ast.friendlyNameForDartOperator[name] ?? name;
      return js_ast.Method(_emitScopedId(name), fn);
    });
    return js_ast.Call(js_ast.PropertyAccess(js_ast.This(), jsMethod.name), []);
  }

  /// If [e] is a [TypeLiteral] or a [TypeLiteralConstant] expression, return
  /// the underlying [DartType], otherwise returns null.
  // TODO(sigmund,nshahan): remove all uses of type literals in the runtime
  // libraries, so that this pattern can be deleted.
  DartType? _getTypeLiteralType(Expression e) {
    if (e is TypeLiteral) return e.type;
    if (e is ConstantExpression) {
      var constant = e.constant;
      if (constant is TypeLiteralConstant) {
        return constant.type.withDeclaredNullability(Nullability.nonNullable);
      }
    }
    return null;
  }

  @override
  js_ast.Expression visitStaticInvocation(StaticInvocation node) {
    var target = node.target;
    if (isInlineJS(target)) return _emitInlineJSCode(node) as js_ast.Expression;
    if (target.isFactory) return _emitFactoryInvocation(node);

    var enclosingLibrary = target.enclosingLibrary;
    if (_isDartLibrary(enclosingLibrary, '_rti') &&
        _inlineTester.canInline(target.function)) {
      // Transform code that would otherwise appear as a static invocation:
      // ```
      // if (_rti._isString(object)) {...}
      // ```
      //
      // to be avoid cost of extra function calls:
      //
      // ```
      // if (typeof object == "string") {...}
      // ```
      var body = node.target.function.body;
      Expression? bodyToInline;
      // Extract the body.
      if (body is ReturnStatement) {
        // Ex: foo() => <body>;
        bodyToInline = body.expression;
      } else if (body is Block) {
        // Ex: foo() { <body> }
        var singleStatement = body.statements.single;
        if (singleStatement is ReturnStatement) {
          bodyToInline = singleStatement.expression;
        }
      }
      if (bodyToInline != null) {
        // Clone the function parameters and create the mappings from the clone
        // to the argument passed.
        var cloner = CloneVisitorNotMembers();
        var originalParameters = target.function.positionalParameters;
        var replacementArguments = node.arguments.positional;
        var replacements = {
          for (var i = 0; i < originalParameters.length; i++)
            originalParameters[i].accept(cloner) as VariableDeclaration:
                replacementArguments[i],
        };
        // Clone the body using the same cloner to ensure the cloned parameters
        // are correctly linked to their accesses.
        var cloneToInline = bodyToInline.accept(cloner);
        // Substitute the use of the parameters with the values passed.
        var replacer = VariableGetReplacer(replacements);
        var replaced = cloneToInline.accept(replacer) as Expression;
        // Compile the result normally and wrap in parenthesis.
        return js.call('(#)', [replaced.accept(this)]);
      }
    }

    if (_isDartInternal(enclosingLibrary)) {
      var args = node.arguments;
      if (args.positional.length == 1 &&
          args.types.length == 1 &&
          args.named.isEmpty &&
          target.name.text == 'unsafeCast') {
        // Optimize some internal SDK calls by avoiding the insertion of a
        // runtime cast.
        return args.positional.single.accept(this);
      } else if (node.arguments.positional.length == 2 &&
          node.arguments.types.length == 1 &&
          node.arguments.named.isEmpty &&
          target.name.text == 'extractTypeArguments') {
        // Inline the extraction and method call at compile time because we
        // don't preserve the original type argument names into the runtime.
        // Those names are needed in the evaluation string used to extract the
        // types from the provided instance.
        // At this time the only two uses of this method are extracting from
        // `Iterable` and `Map`. There are no extension type uses so no need for
        // erasure here.
        var extractionType = node.arguments.types.single;
        if (extractionType is! InterfaceType) {
          throw UnsupportedError(
              'Type arguments can only be extracted from interface types: '
              'found $extractionType (${extractionType.runtimeType}) at '
              '${node.location}');
        }
        var extractionTypeParameters = extractionType.classNode.typeParameters;
        if (extractionTypeParameters.isEmpty) {
          throw UnsupportedError(
              'The extraction type must have type arguments to be extracted: '
              'found $extractionType (${extractionType.runtimeType}) at '
              '${node.location}');
        }
        var extractionTypeParameterNames = extractionTypeParameters
            .map((p) => '${extractionType.classNode.name}.${p.name!}');
        var instance = node.arguments.positional.first.accept(this);
        var function = node.arguments.positional.last.accept(this);
        var extractedTypeArgs = js_ast.ArrayInitializer([
          for (var recipe in extractionTypeParameterNames)
            js.call('#.#(#, "$recipe")', [
              _emitLibraryName(_rtiLibrary),
              _emitMemberName('evalInInstance', memberClass: _rtiClass),
              instance
            ])
        ]);
        return _runtimeCall('dgcall(#, #, [])', [function, extractedTypeArgs]);
      }
    }

    if (_isDartForeignHelper(enclosingLibrary)) {
      var args = node.arguments.positional;
      var typeArgs = node.arguments.types;
      var name = target.name.text;

      if (args.isEmpty) {
        if (typeArgs.isEmpty && name == 'DART_RUNTIME_LIBRARY') {
          return _runtimeModule;
        }
        if (typeArgs.length == 1) {
          if (name == 'TYPE_REF') {
            return _emitType(typeArgs.single);
          }
          if (name == 'LEGACY_TYPE_REF') {
            return _emitType(
                typeArgs.single.withDeclaredNullability(Nullability.legacy));
          }
        }
      }

      if (args.length == 1) {
        if (name == 'getInterceptor') {
          var argExpression = args.single.accept(this);
          return _runtimeCall('getInterceptorForRti(#)', [argExpression]);
        }
        if (name == 'JS_GET_NAME') {
          var staticGet = args.single as StaticGet;
          var enumField = staticGet.target as Field;
          return _emitExpressionForJsGetName(_asJsGetName(enumField));
        }
        if (name == 'JS_CLASS_REF') {
          var constNode = args.single as ConstantExpression;
          var typeConstant = constNode.constant as TypeLiteralConstant;
          var type = typeConstant.type;
          if (type is NullType) {
            return _emitTopLevelName(_coreTypes.deprecatedNullClass);
          }
          if (type is! InterfaceType) {
            throw UnsupportedError(
                'JS_CLASS_REF only supports interface types: found $type '
                '(${type.runtimeType}) at ${node.location}');
          }
          return _emitTopLevelName(type.classNode);
        }
        if (name == 'RAW_DART_FUNCTION_REF') {
          var expression = args.single as ConstantExpression;
          var fn = expression.constant as StaticTearOffConstant;
          return _emitStaticTarget(fn.target);
        }
        if (name == 'JS_GET_FLAG') {
          var flag = args.single as StringLiteral;
          var value = flag.value;
          return switch (value) {
            'DEV_COMPILER' => js.boolean(true),
            'PRINT_LEGACY_STARS' => js.boolean(_options.printLegacyStars),
            'LEGACY' => _options.soundNullSafety
                ? js.boolean(false)
                // When running the new runtime type system with weak null
                // safety this flag gets toggled when performing `is` and `as`
                // checks. This allows DDC to produce optional warnings or
                // errors when tests pass but would fail in sound null safety.
                : _runtimeCall('legacyTypeChecks'),
            'SOUND_NULL_SAFETY' => js.boolean(_options.soundNullSafety),
            'EXTRA_NULL_SAFETY_CHECKS' => _options.soundNullSafety
                ? js.boolean(false)
                // When running the new runtime type system with weak null
                // safety this flag gets toggled when performing `is` and `as`
                // checks. This allows DDC to produce optional warnings or
                // errors when tests pass but would fail in sound null safety.
                : _runtimeCall('extraNullSafetyChecks'),
            'MINIFIED' => js.boolean(false),
            'VARIANCE' =>
              // Variance is turned on by default, but only interfaces that have
              // at least one type parameter with non-legacy variance will have
              // extra information recorded.
              js.boolean(true),
            _ => throw UnsupportedError(
                'Unknown JS_GET_FLAG "$value" at ${node.location}')
          };
        }
      } else if (args.length == 2) {
        if (name == 'JS_EMBEDDED_GLOBAL') return _emitEmbeddedGlobal(node);
        if (name == 'JS_STRING_CONCAT') {
          var left = _visitExpression(args.first);
          var right = _visitExpression(args.last);
          return js.call('# + #', [left, right]);
        }
      }
      if (name == 'JS_BUILTIN') {
        var staticGet = args[1] as StaticGet;
        var enumField = staticGet.target as Field;
        return _emitOperationForJsBuiltIn(_asJsBuiltin(enumField));
      }
      if (name == 'JS_RAW_EXCEPTION') {
        // Serves as a way to access the wrapped JS exception.
        return _emitVariableRef(_rethrowParameter!);
      }
      if (name == 'JS_RTI_PARAMETER') {
        return _rtiParam;
      }
    }

    if (_isSdkInternalRuntime(enclosingLibrary)) {
      var name = target.name.text;
      if (node.arguments.positional.length == 1) {
        var firstArg = node.arguments.positional.single;
        if (name == 'extensionSymbol' && firstArg is StringLiteral) {
          return _getSymbol(_getExtensionSymbolInternal(firstArg.value));
        }
      } else if (node.arguments.positional.length == 2) {
        var firstArg = node.arguments.positional[0];
        var secondArg = node.arguments.positional[1];
        var type = _getTypeLiteralType(secondArg);
        if (name == '_jsInstanceOf' &&
            type is InterfaceType &&
            type.typeArguments.isEmpty) {
          return js.call('# instanceof #',
              [_visitExpression(firstArg), _emitTopLevelName(type.classNode)]);
        }
      }
    }
    if (_isDartJsHelper(enclosingLibrary)) {
      var name = target.name.text;
      if (name == 'jsObjectGetPrototypeOf') {
        var obj = node.arguments.positional.single;
        return _emitJSObjectGetPrototypeOf(_visitExpression(obj),
            fullyQualifiedName: false);
      }
      if (name == 'jsObjectSetPrototypeOf') {
        var obj = node.arguments.positional.first;
        var prototype = node.arguments.positional.last;
        return _emitJSObjectSetPrototypeOf(
            _visitExpression(obj), _visitExpression(prototype),
            fullyQualifiedName: false);
      }
    }
    if (target.isExternal &&
        target.isExtensionTypeMember &&
        target.function.namedParameters.isNotEmpty) {
      // JS interop checks assert that only external extension type constructors
      // and factories have named parameters.
      assert(target.function.positionalParameters.isEmpty);
      return _emitObjectLiteral(
          Arguments(node.arguments.positional,
              types: node.arguments.types, named: node.arguments.named),
          target);
    }
    if (target == _coreTypes.identicalProcedure) {
      return _emitCoreIdenticalCall(node.arguments.positional);
    }
    if (_isDebuggerCall(target)) {
      return _emitDebuggerCall(node) as js_ast.Expression;
    }
    if (_isDartJsUtil(enclosingLibrary)) {
      // We try and do further inlining here for the unchecked/trusted-type
      // variants of js_util methods. Note that we only lower the methods that
      // are used in transformations and are private. Also note that this
      // inlining ignores `sdk/lib/_internal/js_shared/lib/js_util_patch.dart`'s
      // implementations for the lowered methods.
      //
      // If you update the code there, you should update the code here.
      // Long-term, we'll need a better IR to lower interop methods to, or a DDC
      // inliner to do the inlining for us.
      var name = target.name.text;
      if (name == '_getPropertyTrustType') {
        return js_ast.PropertyAccess(
            _visitExpression(node.arguments.positional[0]),
            _visitExpression(node.arguments.positional[1]));
      } else if (name == '_setPropertyUnchecked') {
        return _visitExpression(node.arguments.positional[2])
            .toAssignExpression(js_ast.PropertyAccess(
                _visitExpression(node.arguments.positional[0]),
                _visitExpression(node.arguments.positional[1])));
      } else if (RegExp(r'^\_callMethodUnchecked(TrustType)?[0-4]')
          .hasMatch(name)) {
        // Note that we don't lower `_callMethodTrustType`. This is because it
        // uses `assertInterop` checks.
        var trustType = name.contains('TrustType');
        var args = <js_ast.Expression>[];
        assert(node.arguments.named.isEmpty);
        // Ignore the receiver and name of the method.
        for (var i = 2; i < node.arguments.positional.length; i++) {
          args.add(_visitExpression(node.arguments.positional[i]));
        }
        js_ast.Expression call = js_ast.Call(
            js_ast.PropertyAccess(
                _visitExpression(node.arguments.positional[0]),
                _visitExpression(node.arguments.positional[1])),
            args);
        if (!trustType) {
          call = _emitCast(call, node.arguments.types[0]);
        }
        return call;
      } else if (RegExp(r'^\_callConstructorUnchecked[0-4]').hasMatch(name)) {
        var args = <js_ast.Expression>[];
        assert(node.arguments.named.isEmpty);
        // Ignore the constructor.
        for (var i = 1; i < node.arguments.positional.length; i++) {
          args.add(_visitExpression(node.arguments.positional[i]));
        }
        return _emitCast(
            js_ast.New(_visitExpression(node.arguments.positional[0]), args),
            node.arguments.types[0]);
      }
    }

    var fn = _emitStaticTarget(target);
    var args = _emitArgumentList(node.arguments, target: target);
    var staticCall = js_ast.Call(fn, args);
    return _isNullCheckableJsInterop(target)
        ? _wrapWithJsInteropNullCheck(staticCall)
        : staticCall;
  }

  js_ast.Expression _emitJSObjectGetPrototypeOf(js_ast.Expression obj,
          {required bool fullyQualifiedName}) =>
      fullyQualifiedName
          ? _runtimeCall('global.Object.getPrototypeOf(#)', [obj])
          : js.call('Object.getPrototypeOf(#)', obj);

  js_ast.Expression _emitJSObjectSetPrototypeOf(
          js_ast.Expression obj, js_ast.Expression prototype,
          {required bool fullyQualifiedName}) =>
      fullyQualifiedName
          ? _runtimeCall('global.Object.setPrototypeOf(#, #)', [obj, prototype])
          : js.call('Object.setPrototypeOf(#, #)', [obj, prototype]);

  bool _isDebuggerCall(Procedure target) {
    return target.name.text == 'debugger' &&
        target.enclosingLibrary.importUri.toString() == 'dart:developer';
  }

  js_ast.Node _emitDebuggerCall(StaticInvocation node) {
    var args = node.arguments.named;
    var isStatement = node.parent is ExpressionStatement;
    var debuggerStatement =
        js_ast.DebuggerStatement().withSourceInformation(_nodeStart(node));
    if (args.isEmpty) {
      // Inline `debugger()` with no arguments, as a statement if possible,
      // otherwise as an immediately invoked function.
      return isStatement
          ? debuggerStatement
          : js.call('(() => { #; return true})()', [debuggerStatement]);
    }

    // The signature of `debugger()` is:
    //
    //     bool debugger({bool when: true, String message})
    //
    // This code path handles the named arguments `when` and/or `message`.
    // Both must be evaluated in the supplied order, and then `when` is used
    // to decide whether to break or not.
    //
    // We also need to return the value of `when`.
    var jsArgs = args.map(_emitNamedExpression).toList();
    var when = args.length == 1
        // For a single `when` argument, use it.
        //
        // For a single `message` argument, use `{message: ...}`, which
        // coerces to true (the default value of `when`).
        ? (args[0].name == 'when'
            ? jsArgs[0].value
            : js_ast.ObjectInitializer(jsArgs))
        // If we have both `message` and `when` arguments, evaluate them in
        // order, then extract the `when` argument.
        : js.call('#.when', js_ast.ObjectInitializer(jsArgs));
    return isStatement
        ? js.statement('if (#) #;', [when, debuggerStatement])
        : js.call(
            '# && (() => { #; return true })()', [when, debuggerStatement]);
  }

  /// Emits the target of a [StaticInvocation], [StaticGet], or [StaticSet].
  js_ast.Expression _emitStaticTarget(Member target) {
    var c = target.enclosingClass;
    if (c != null) {
      // A static native element should just forward directly to the JS type's
      // member, for example `Css.supports(...)` in dart:html should be replaced
      // by a direct call to the DOM API: `global.CSS.supports`.
      var isExternal = _isExternal(target);
      if (isExternal && (target as Procedure).isStatic) {
        var nativeName = _extensionTypes.getNativePeers(c);
        if (nativeName.isNotEmpty) {
          var memberName = _annotationName(target, isJSName) ??
              _emitStaticMemberName(target.name.text, target);
          return _runtimeCall('global.#.#', [nativeName[0], memberName]);
        }
      }
      return js_ast.PropertyAccess(_emitStaticClassName(c, isExternal),
          _emitStaticMemberName(target.name.text, target));
    }
    return _emitTopLevelName(target);
  }

  List<js_ast.Expression> _emitArgumentList(Arguments node,
      {bool types = true, Member? target}) {
    types = types && _reifyGenericFunction(target);
    final isJsInterop = target != null && isJsMember(target);
    return [
      if (types)
        for (var typeArg in node.types) _emitType(typeArg),
      for (var arg in node.positional)
        if (arg is StaticInvocation &&
            isJSSpreadInvocation(arg.target) &&
            arg.arguments.positional.length == 1)
          js_ast.Spread(_visitExpression(arg.arguments.positional[0]))
        else if (isJsInterop)
          _visitExpression(_assertInterop(arg))
        else
          _visitExpression(arg),
      if (node.named.isNotEmpty)
        js_ast.ObjectInitializer([
          for (var arg in node.named) _emitNamedExpression(arg, isJsInterop)
        ]),
    ];
  }

  js_ast.Property _emitNamedExpression(NamedExpression arg,
      [bool isJsInterop = false]) {
    var value = isJsInterop ? _assertInterop(arg.value) : arg.value;
    return js_ast.Property(_propertyName(arg.name), _visitExpression(value));
  }

  /// Emits code for the `JS(...)` macro.
  js_ast.Node _emitInlineJSCode(StaticInvocation node) {
    var args = node.arguments.positional;
    // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
    var code = args[1];
    List<Expression> templateArgs;
    String source;
    if (code is ConstantExpression) {
      templateArgs = args.skip(2).toList();
      source = (code.constant as StringConstant).value;
    } else if (code is StringConcatenation) {
      if (code.expressions.every((e) => e is StringLiteral)) {
        templateArgs = args.skip(2).toList();
        source = code.expressions.map((e) => (e as StringLiteral).value).join();
      } else {
        if (args.length > 2) {
          throw ArgumentError(
              "Can't mix template args and string interpolation in JS calls: "
              '`$node`');
        }
        templateArgs = <Expression>[];
        source = code.expressions.map((expression) {
          if (expression is StringLiteral) {
            return expression.value;
          } else {
            templateArgs.add(expression);
            return '#';
          }
        }).join();
      }
    } else {
      templateArgs = args.skip(2).toList();
      source = (code as StringLiteral).value;
    }

    // TODO(jmesserly): arguments to JS() that contain type literals evaluate to
    // the raw runtime type instead of the wrapped Type object.
    // We can clean this up by switching to `unwrapType(<type literal>)`, which
    // the compiler will then optimize.
    var wasInForeignJS = _isInForeignJS;
    _isInForeignJS = true;
    var jsArgs = templateArgs.map(_visitExpression).toList();
    _isInForeignJS = wasInForeignJS;

    var result = js.parseForeignJS(source).instantiate(jsArgs);

    // Add a check to make sure any JS() values from a native type are typed
    // properly in sound null-safety.
    if (_isWebLibrary(_currentLibrary!.importUri) && _options.soundNullSafety) {
      var type = node.getStaticType(_staticTypeContext);
      if (type.isPotentiallyNonNullable) {
        result = _runtimeCall('checkNativeNonNull(#)', [result]);
      }
    }

    assert(result is js_ast.Expression ||
        result is js_ast.Statement && node.parent is ExpressionStatement);
    return result.withSourceInformation(_nodeStart(node));
  }

  js_ast.Expression _emitEmbeddedGlobal(StaticInvocation node) {
    var constantExpression = node.arguments.positional[1] as ConstantExpression;
    var name = constantExpression.constant as StringConstant;
    var value = name.value;
    if (value == 'arrayRti') {
      // Special case for the rti on a JSArray. These are defined via the dartx
      // extension functionality.
      return _emitMemberName('arrayRti', memberClass: _jsArrayClass);
    }
    return _runtimeCall('#', [name.value]);
  }

  /// Returns the string literal that is to be used as the result of a call to
  /// [JS_GET_NAME] for [name].
  js_ast.Expression _emitExpressionForJsGetName(JsGetName name) {
    switch (name) {
      case JsGetName.OPERATOR_IS_PREFIX:
        return js.string(js_ast.FixedNames.operatorIsPrefix);
      case JsGetName.SIGNATURE_NAME:
        return _runtimeCall(
            '#', [js.string(js_ast.FixedNames.operatorSignature)]);
      case JsGetName.RTI_NAME:
        return js.string(js_ast.FixedNames.rtiName);
      case JsGetName.FUTURE_CLASS_TYPE_NAME:
        return js.string(
            _typeRecipeGenerator.interfaceTypeRecipe(_coreTypes.futureClass));
      case JsGetName.LIST_CLASS_TYPE_NAME:
        return js.string(
            _typeRecipeGenerator.interfaceTypeRecipe(_coreTypes.listClass));
      case JsGetName.RTI_FIELD_AS:
        return _emitMemberName(js_ast.FixedNames.rtiAsField,
            memberClass: _rtiClass);
      case JsGetName.RTI_FIELD_IS:
        return _emitMemberName(js_ast.FixedNames.rtiIsField,
            memberClass: _rtiClass);
      default:
        throw UnsupportedError('JsGetName has no name for "$name".');
    }
  }

  /// Returns the expression that is to be used as the result of a call to
  /// [JS_BUILTIN] for [builtin].
  js_ast.Expression _emitOperationForJsBuiltIn(JsBuiltin builtin) {
    switch (builtin) {
      case JsBuiltin.dartClosureConstructor:
        // TODO(48585) Is this safe or will it conflict with functions that
        // enter the program through JS Interop?
        return js.call('Function');
      case JsBuiltin.dartObjectConstructor:
        return _emitTopLevelName(_coreTypes.objectClass);
      default:
        throw UnsupportedError('JsBuiltin has no operation for "$builtin".');
    }
  }

  String _enumValueName(Field field) {
    var enumName = field.enclosingClass!.name;
    var valueName = field.name.text;
    return '$enumName.$valueName';
  }

  JsGetName _asJsGetName(Field field) => JsGetName.values
      .firstWhere((val) => val.toString() == _enumValueName(field));

  JsBuiltin _asJsBuiltin(Field field) => JsBuiltin.values
      .firstWhere((val) => val.toString() == _enumValueName(field));

  bool _isWebLibrary(Uri importUri) =>
      importUri.isScheme('dart') &&
      (importUri.path == 'html' ||
          importUri.path == 'svg' ||
          importUri.path == 'indexed_db' ||
          importUri.path == 'web_audio' ||
          importUri.path == 'web_gl' ||
          importUri.path == 'web_sql' ||
          importUri.path == 'html_common');

  bool _isNull(Expression expr) =>
      expr is NullLiteral ||
      expr.getStaticType(_staticTypeContext).extensionTypeErasure is NullType;

  bool _doubleEqIsIdentity(Expression left, Expression right) {
    // If we statically know LHS or RHS is null we can use ==.
    if (_isNull(left) || _isNull(right)) return true;
    // If the representation of the  two types will not induce conversion in
    // JS then we can use == .
    return !_typeRep.equalityMayConvert(left.getStaticType(_staticTypeContext),
        right.getStaticType(_staticTypeContext));
  }

  bool _tripleEqIsIdentity(Expression left, Expression right) {
    // If either is non-nullable, then we don't need to worry about
    // equating null and undefined, and so we can use triple equals.
    return !_isNullable(left) || !_isNullable(right);
  }

  /// Returns true if [expr] can be null.
  bool _isNullable(Expression expr) {
    if (_isDartLibrary(_currentLibrary!, '_rti') ||
        _isSdkInternalRuntime(_currentLibrary!)) {
      _nullableInference.treatDeclaredTypesAsSound = true;
    }
    final result = _nullableInference.isNullable(expr);
    _nullableInference.treatDeclaredTypesAsSound = false;
    return result;
  }

  js_ast.Expression _emitJSDoubleEq(List<js_ast.Expression> args,
      {bool negated = false}) {
    var op = negated ? '# != #' : '# == #';
    return js.call(op, args);
  }

  js_ast.Expression _emitJSTripleEq(List<js_ast.Expression> args,
      {bool negated = false}) {
    var op = negated ? '# !== #' : '# === #';
    return js.call(op, args);
  }

  js_ast.Expression _emitCoreIdenticalCall(List<Expression> args,
      {bool negated = false}) {
    if (args.length != 2) {
      // Shouldn't happen in typechecked code
      return _runtimeCall(
          'throw(Error("compile error: calls to `identical` require 2 args")');
    }
    var left = args[0];
    var right = args[1];
    var jsArgs = [_visitExpression(left), _visitExpression(right)];
    if (_tripleEqIsIdentity(left, right)) {
      return _emitJSTripleEq(jsArgs, negated: negated);
    }
    if (_doubleEqIsIdentity(left, right)) {
      return _emitJSDoubleEq(jsArgs, negated: negated);
    }
    var code = negated ? '!#' : '#';
    return js.call(code,
        js_ast.Call(_emitTopLevelName(_coreTypes.identicalProcedure), jsArgs));
  }

  /// Returns true if this [member] is a JS interop member.
  bool isJSInteropMember(Member member) =>
      member.isExternal && hasJSInteropAnnotation(member.enclosingClass!);

  @override
  js_ast.Expression visitConstructorInvocation(ConstructorInvocation node) {
    var ctor = node.target;
    var ctorClass = ctor.enclosingClass;
    var args = node.arguments;
    if (isJSAnonymousType(ctorClass)) return _emitObjectLiteral(args, ctor);
    // JS interop constructor calls do not provide an RTI at the call site.
    var shouldProvideRti =
        !isJSInteropMember(ctor) && _requiresRtiForInstantiation(ctorClass);
    var rti = shouldProvideRti
        ? _emitType(node.constructedType,
            emitJSInteropGenericClassTypeParametersAsAny: false)
        : null;
    var result = js_ast.New(
      _emitConstructorName(node.constructedType, ctor),
      [
        if (rti != null) rti,
        ..._emitArgumentList(args, types: false, target: ctor)
      ],
    );
    return node.isConst ? _canonicalizeConstObject(result) : result;
  }

  js_ast.Expression _emitFactoryInvocation(StaticInvocation node) {
    var args = node.arguments;
    var ctor = node.target;
    var ctorClass = ctor.enclosingClass!;
    // JS interop constructor calls do not require an RTI at the call site.
    if (isJSInteropMember(ctor)) {
      return _emitJSInteropNew(ctor, args);
    }

    var type = ctorClass.typeParameters.isEmpty
        ? _coreTypes.nonNullableRawType(ctorClass)
        : InterfaceType(ctorClass, Nullability.nonNullable, args.types);

    if (isFromEnvironmentInvocation(_coreTypes, node)) {
      var value = _constants.evaluate(node);
      if (value is PrimitiveConstant) {
        return visitConstant(value);
      }
    }

    if (args.positional.isEmpty &&
        args.named.isEmpty &&
        ctorClass.enclosingLibrary.importUri.isScheme('dart')) {
      // Skip the slow SDK factory constructors when possible.
      switch (ctorClass.name) {
        case 'Map':
        case 'HashMap':
        case 'LinkedHashMap':
          if (ctor.name.text == '') {
            var mapType = _createMapImplType(type);
            var mapClass = _emitClassRef(mapType);
            var rti = _emitType(mapType);
            return js.call('new #.new(#)', [mapClass, rti]);
          } else if (ctor.name.text == 'identity') {
            var mapType = _createMapImplType(type, identity: true);
            var mapClass = _emitClassRef(mapType);
            var rti = _emitType(mapType);
            return js.call('new #.new(#)', [mapClass, rti]);
          }
        case 'Set':
        case 'HashSet':
        case 'LinkedHashSet':
          if (ctor.name.text == '') {
            var setType = _createSetImplType(type);
            var setClass = _emitClassRef(setType);
            var rti = _emitType(setType);
            return js.call('new #.new(#)', [setClass, rti]);
          } else if (ctor.name.text == 'identity') {
            var setType = _createSetImplType(type, identity: true);
            var setClass = _emitClassRef(setType);
            var rti = _emitType(setType);
            return js.call('new #.new(#)', [setClass, rti]);
          }
        case 'List':
          if (ctor.name.text == '') {
            return _emitList(type.typeArguments[0], []);
          }
      }
    }
    var rti = _requiresRtiForInstantiation(ctorClass)
        ? _emitType(type, emitJSInteropGenericClassTypeParametersAsAny: false)
        : null;
    var result = js_ast.Call(_emitConstructorName(type, ctor),
        [if (rti != null) rti, ..._emitArgumentList(args, types: false)]);
    return node.isConst ? _canonicalizeConstObject(result) : result;
  }

  js_ast.Expression _emitJSInteropNew(Member ctor, Arguments args) {
    var ctorClass = ctor.enclosingClass!;
    if (isJSAnonymousType(ctorClass)) return _emitObjectLiteral(args, ctor);
    // JS interop constructor calls do not require an RTI at the call site.
    return js_ast.New(
        _emitConstructorName(_coreTypes.nonNullableRawType(ctorClass), ctor),
        _emitArgumentList(args, types: false, target: ctor));
  }

  InterfaceType _createMapImplType(InterfaceType type, {bool? identity}) {
    var typeArgs = type.typeArguments;
    if (typeArgs.isEmpty) {
      return type.withDeclaredNullability(Nullability.nonNullable);
    }
    identity ??= _typeRep.isPrimitive(typeArgs[0]);
    var c = identity ? _identityHashMapImplClass : _linkedHashMapImplClass;
    return InterfaceType(c, Nullability.nonNullable, typeArgs);
  }

  InterfaceType _createSetImplType(InterfaceType type, {bool? identity}) {
    var typeArgs = type.typeArguments;
    if (typeArgs.isEmpty) {
      return type.withDeclaredNullability(Nullability.nonNullable);
    }
    identity ??= _typeRep.isPrimitive(typeArgs[0]);
    var c = identity ? _identityHashSetImplClass : _linkedHashSetImplClass;
    return InterfaceType(c, Nullability.nonNullable, typeArgs);
  }

  js_ast.Expression _emitObjectLiteral(Arguments node, Member ctor) {
    var args = _emitArgumentList(node, types: false, target: ctor);
    if (args.isEmpty) return js.call('{}');
    assert(args.single is js_ast.ObjectInitializer);
    return args.single;
  }

  @override
  js_ast.Expression visitNot(Not node) {
    var operand = node.operand;
    if (operand is EqualsCall) {
      return _emitEqualityOperator(
          operand.left, operand.interfaceTarget, operand.right,
          negated: true);
    } else if (operand is EqualsNull) {
      return _emitCoreIdenticalCall([operand.expression, NullLiteral()],
          negated: true);
    } else if (operand is StaticInvocation &&
        operand.target == _coreTypes.identicalProcedure) {
      return _emitCoreIdenticalCall(operand.arguments.positional,
          negated: true);
    }

    var jsOperand = _visitTest(operand);
    if (jsOperand is js_ast.LiteralBool) {
      // Flipping the value here for `!true` or `!false` allows for simpler
      // `if (true)` or `if (false)` detection and optimization.
      return js_ast.LiteralBool(!jsOperand.value)
              .withSourceInformation(jsOperand.sourceInformation)
          as js_ast.LiteralBool;
    }

    // Logical negation, `!e`, is a boolean conversion context since it is
    // defined as `e ? false : true`.
    return js.call('!#', jsOperand).withSourceInformation(continueSourceMap);
  }

  @override
  js_ast.Expression visitNullCheck(NullCheck node) {
    var expr = node.operand;
    var jsExpr = _visitExpression(expr);
    // If the expression is non-nullable already, this is a no-op.
    return _isNullable(expr) ? _runtimeCall('nullCheck(#)', [jsExpr]) : jsExpr;
  }

  @override
  js_ast.Expression visitLogicalExpression(LogicalExpression node) {
    // The operands of logical boolean operators are subject to boolean
    // conversion.
    return _visitTest(node);
  }

  @override
  js_ast.Expression visitConditionalExpression(ConditionalExpression node) {
    var condition = _visitTest(node.condition);
    if (condition is js_ast.LiteralBool) {
      if (condition.value) {
        // Avoid emitting conditional when one branch is effectively dead code.
        // ex: `true ? foo : bar` -> `foo`
        return _visitExpression(node.then);
      } else {
        // ex: `false ? foo : bar` -> `bar`
        return _visitExpression(node.otherwise);
      }
    }
    var then = _visitExpression(node.then);
    var otherwise = _visitExpression(node.otherwise);
    return js.call('# ? # : #', [condition, then, otherwise])
      ..sourceInformation =
          condition.sourceInformation ?? _nodeStart(node.condition);
  }

  @override
  js_ast.Expression visitStringConcatenation(StringConcatenation node) {
    var parts = <js_ast.Expression>[];
    for (var e in node.expressions) {
      var jsExpr = _visitExpression(e);
      if (jsExpr is js_ast.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
        continue;
      }
      var type = e.getStaticType(_staticTypeContext).extensionTypeErasure;
      if (DartTypeEquivalence(_coreTypes, ignoreTopLevelNullability: true)
              .areEqual(type, _coreTypes.stringNonNullableRawType) &&
          !_isNullable(e)) {
        parts.add(jsExpr);
      } else if (_shouldCallObjectMemberHelper(e)) {
        parts.add(_runtimeCall('str(#)', [jsExpr]));
      } else {
        // It is safe to call a version of `str()` that does not probe for the
        // toString method before calling it.
        parts.add(_runtimeCall('strSafe(#)', [jsExpr]));
      }
    }
    if (parts.isEmpty) return js.string('');
    return js_ast.Expression.binary(parts, '+');
  }

  @override
  js_ast.Expression visitListConcatenation(ListConcatenation node) {
    // Only occurs inside unevaluated constants.
    throw UnsupportedError('List concatenation');
  }

  @override
  js_ast.Expression visitSetConcatenation(SetConcatenation node) {
    // Only occurs inside unevaluated constants.
    throw UnsupportedError('Set concatenation');
  }

  @override
  js_ast.Expression visitMapConcatenation(MapConcatenation node) {
    // Only occurs inside unevaluated constants.
    throw UnsupportedError('Map concatenation');
  }

  @override
  js_ast.Expression visitInstanceCreation(InstanceCreation node) {
    // Only occurs inside unevaluated constants.
    throw UnsupportedError('Instance creation');
  }

  @override
  js_ast.Expression visitFileUriExpression(FileUriExpression node) {
    // Only occurs inside unevaluated constants.
    throw UnsupportedError('File URI expression');
  }

  @override
  js_ast.Expression visitConstructorTearOff(ConstructorTearOff node) {
    throw UnsupportedError('Constructor tear off');
  }

  @override
  js_ast.Expression visitRedirectingFactoryTearOff(
      RedirectingFactoryTearOff node) {
    throw UnsupportedError('RedirectingFactory tear off');
  }

  @override
  js_ast.Expression visitTypedefTearOff(TypedefTearOff node) {
    throw UnsupportedError('Typedef instantiation');
  }

  @override
  js_ast.Expression visitIsExpression(IsExpression node) {
    return _emitIsExpression(node.operand, node.type.extensionTypeErasure);
  }

  js_ast.Expression _emitIsExpression(Expression operand, DartType type) {
    // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
    var lhs = _visitExpression(operand);
    // It is invalid to use a simplified check for a native type in place of
    // a type test for a `TypeParameterType`. This is because at runtime type
    // parameters can be instantiated as the bottom type `Never` and
    // `val is Never` should always evaluate to false.
    var typeofName =
        type is TypeParameterType || type is StructuralParameterType
            ? null
            : _typeRep.typeFor(type).primitiveTypeOf;
    // Inline non-nullable primitive types other than int (which requires a
    // Math.floor check).
    if (typeofName != null &&
        type.nullability == Nullability.nonNullable &&
        type != _types.coreTypes.intNonNullableRawType) {
      return js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
    }

    return js.call('#.#(#)', [
      _emitType(type),
      _emitMemberName(js_ast.FixedNames.rtiIsField, memberClass: _rtiClass),
      lhs
    ]);
  }

  @override
  js_ast.Expression visitAsExpression(AsExpression node) {
    var fromExpr = node.operand;
    var jsFrom = _visitExpression(fromExpr);
    if (node.isUnchecked) return jsFrom;
    var to = node.type.extensionTypeErasure;
    var from = fromExpr.getStaticType(_staticTypeContext).extensionTypeErasure;

    // If the check was put here by static analysis to ensure soundness, we
    // can't skip it. For example, one could implement covariant generic caller
    // side checks like this:
    //
    //      typedef F<T>(T t);
    //      class C<T> {
    //        F<T> f;
    //        add(T t) {
    //          // required check `t as T`
    //        }
    //      }
    //      main() {
    //        C<Object> c = new C<int>()..f = (int x) => x.isEven;
    //        c.f('hi'); // required check `c.f as F<Object>`
    //        c.add('hi);
    //      }
    //
    var isTypeError = node.isTypeError;
    if (!isTypeError &&
        _types.isSubtypeOf(from, to, SubtypeCheckMode.withNullabilities)) {
      return jsFrom;
    }

    if (!isTypeError &&
        DartTypeEquivalence(_coreTypes, ignoreTopLevelNullability: true)
            .areEqual(from, to) &&
        _mustBeNonNullable(to)) {
      // If the underlying type is the same, we only need a null check.
      return _runtimeCall('nullCast(#, #)', [jsFrom, _emitType(to)]);
    }

    // All Dart number types map to a JS double.  We can specialize these
    // cases.
    if (_typeRep.isNumber(from) && _typeRep.isNumber(to)) {
      // If `to` is some form of `num`, it should have been filtered above.

      // * -> double? | double* : no-op
      if (to == _coreTypes.doubleLegacyRawType ||
          to == _coreTypes.doubleNullableRawType) {
        return jsFrom;
      }

      // * -> double : null check
      if (to == _coreTypes.doubleNonNullableRawType) {
        if (from.nullability == Nullability.nonNullable) {
          return jsFrom;
        }
        return _runtimeCall('nullCast(#, #)', [jsFrom, _emitType(to)]);
      }

      // * -> int : asInt check
      if (to == _coreTypes.intNonNullableRawType) {
        return _runtimeCall('asInt(#)', [jsFrom]);
      }

      // * -> int? | int* : asNullableInt check
      if (to == _coreTypes.intLegacyRawType ||
          to == _coreTypes.intNullableRawType) {
        return _runtimeCall('asNullableInt(#)', [jsFrom]);
      }
    }

    return _emitCast(jsFrom, to);
  }

  js_ast.Expression _emitCast(js_ast.Expression expr, DartType type) {
    var normalizedType = type.extensionTypeErasure;
    if (_types.isTop(normalizedType)) return expr;
    return js.call('#.#(#)', [
      _emitType(normalizedType),
      _emitMemberName(js_ast.FixedNames.rtiAsField, memberClass: _rtiClass),
      expr
    ]);
  }

  @override
  js_ast.Expression visitSymbolLiteral(SymbolLiteral node) =>
      _emitDartSymbol(node.value);

  @override
  js_ast.Expression visitTypeLiteral(TypeLiteral node) =>
      _emitTypeLiteral(node.type);

  js_ast.Expression _emitTypeLiteral(DartType type) {
    var typeRep = _emitType(type);

    // TODO(46002) All `JS()` calls in the SDK should be explicit when using the
    // internal rti object by calling the `TYPE_REF` helper.
    if (_isInForeignJS) return typeRep;

    // If the type is a type literal expression in Dart code, wrap the raw
    // runtime type in a "Type" instance.
    return js.call(
        '#.createRuntimeType(#)', [_emitLibraryName(_rtiLibrary), typeRep]);
  }

  @override
  js_ast.Expression visitThisExpression(ThisExpression node) => js_ast.This();

  @override
  js_ast.Expression visitRethrow(Rethrow node) {
    return _runtimeCall('rethrow(#)', [_emitVariableRef(_rethrowParameter!)]);
  }

  @override
  js_ast.Expression visitThrow(Throw node) =>
      _runtimeCall('throw(#)', [_visitExpression(node.expression)]);

  @override
  js_ast.Expression visitListLiteral(ListLiteral node) {
    var elementType = node.typeArgument;
    var elements = _visitExpressionList(node.expressions);
    return _emitList(elementType, elements);
  }

  js_ast.Expression _emitList(
      DartType itemType, List<js_ast.Expression> items) {
    var list = js_ast.ArrayInitializer(items);

    // List's type parameter is default-initialized to dynamic in our runtime.
    if (itemType == const DynamicType()) return list;

    // Call `new JSArray<E>.of(list)`
    var type =
        InterfaceType(_jsArrayClass, Nullability.nonNullable, [itemType]);
    var arrayClass = _emitClassRef(type);
    var arrayRti = _emitType(type);
    return js.call('#.of(#, #)', [arrayClass, arrayRti, list]);
  }

  js_ast.Expression _emitConstList(
      DartType elementType, List<js_ast.Expression> elements) {
    // dart.constList helper internally depends on _interceptors.JSArray.
    _declareBeforeUse(_jsArrayClass);
    return _runtimeCall(
        'constList(#, [#])', [_emitType(elementType), elements]);
  }

  @override
  js_ast.Expression visitSetLiteral(SetLiteral node) {
    // TODO(markzipan): remove const check when we use front-end const eval
    if (!node.isConst) {
      var type = InterfaceType(
          _linkedHashSetClass, Nullability.nonNullable, [node.typeArgument]);
      var setClass = _emitClassRef(type);
      var rti = _emitType(type);
      if (node.expressions.isEmpty) {
        return js.call('#.new(#)', [setClass, rti]);
      }
      return js.call('#.from(#, [#])',
          [setClass, rti, _visitExpressionList(node.expressions)]);
    }
    return _emitConstSet(
        node.typeArgument, _visitExpressionList(node.expressions));
  }

  js_ast.Expression _emitConstSet(
      DartType elementType, List<js_ast.Expression> elements) {
    return _runtimeCall('constSet(#, [#])', [_emitType(elementType), elements]);
  }

  @override
  js_ast.Expression visitMapLiteral(MapLiteral node) {
    var entries = [
      for (var e in node.entries) ...[
        _visitExpression(e.key),
        _visitExpression(e.value),
      ],
    ];

    // TODO(markzipan): remove const check when we use front-end const eval
    if (!node.isConst) {
      var type = node.getStaticType(_staticTypeContext) as InterfaceType;
      var mapType = _createMapImplType(type);
      var mapClass = _emitClassRef(mapType);
      var rti = _emitType(mapType);
      if (node.entries.isEmpty) {
        return js.call('new #.new(#)', [mapClass, rti]);
      }
      return js.call('new #.from(#, [#])', [mapClass, rti, entries]);
    }
    return _emitConstMap(node.keyType, node.valueType, entries);
  }

  js_ast.Expression _emitConstMap(
      DartType keyType, DartType valueType, List<js_ast.Expression> entries) {
    return _runtimeCall('constMap(#, #, [#])',
        [_emitType(keyType), _emitType(valueType), entries]);
  }

  /// Returns the key used for shape lookup at runtime.
  ///
  /// See `shapes` in dart:_runtime (records.dart) for a description.
  String _recordShapeKey(
      int positionalElementCount, Iterable<String> namedElementNames) {
    var elementCount = positionalElementCount + namedElementNames.length;
    return '$elementCount;${namedElementNames.join(',')}';
  }

  @override
  js_ast.Expression visitRecordLiteral(RecordLiteral node) {
    var names = node.named.map((element) => element.name);
    var positionalElementCount = node.positional.length;
    var shapeKey = _recordShapeKey(positionalElementCount, names);
    var shapeExpr = _runtimeCall('recordLiteral(#, #, #, [#])', [
      js.string(shapeKey),
      js.number(positionalElementCount),
      names.isEmpty ? js.call('void 0') : js.stringArray(names),
      [
        for (var positional in node.positional) _visitExpression(positional),
        for (var named in node.named) _visitExpression(named.value),
      ]
    ]);
    return shapeExpr;
  }

  @override
  js_ast.Expression visitAwaitExpression(AwaitExpression node) {
    var expression = _visitExpression(node.operand);
    var type = node.runtimeCheckType;
    if (type != null) {
      // When an expected runtime type is present there is a possible soundness
      // issue with the static types. The type of the await expression must be
      // checked at runtime to ensure soundness.
      var expectedType = _emitType(type);
      var asyncLibrary = _emitLibraryName(_coreTypes.asyncLibrary);
      expression = js.call('#.awaitWithTypeCheck(#, #)',
          [asyncLibrary, expectedType, expression]);
    }
    return js_ast.Await(expression);
  }

  @override
  js_ast.Expression visitFunctionExpression(FunctionExpression node) {
    var fn = _emitArrowFunction(node);
    if (!_reifyFunctionType(node.function)) return fn;
    return _emitFunctionTagged(
        fn, node.getStaticType(_staticTypeContext) as FunctionType);
  }

  js_ast.ArrowFun _emitArrowFunction(FunctionExpression node) {
    var f = _emitFunction(node.function, null);
    js_ast.Node body = f.body;

    // Simplify `=> { return e; }` to `=> e`
    if (body is js_ast.Block) {
      var block = body;
      if (block.statements.length == 1) {
        var s = block.statements.single;
        if (s is js_ast.Block) {
          block = s;
          if (block.statements.length == 1) s = block.statements.single;
        }
        if (s is js_ast.Return && s.value != null) body = s.value!;
      }
    }

    // Convert `function(...) { ... }` to `(...) => ...`
    // This is for readability, but it also ensures correct `this` binding.
    return js_ast.ArrowFun(f.params, body);
  }

  @override
  js_ast.Expression visitStringLiteral(StringLiteral node) =>
      js.escapedString(node.value, '"');

  @override
  js_ast.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);

  @override
  js_ast.Expression visitDoubleLiteral(DoubleLiteral node) =>
      js.number(node.value);

  @override
  js_ast.Expression visitBoolLiteral(BoolLiteral node) =>
      js_ast.LiteralBool(node.value);

  @override
  js_ast.Expression visitNullLiteral(NullLiteral node) => js_ast.LiteralNull();

  @override
  js_ast.Expression visitLet(Let node) {
    var v = node.variable;
    var init = _visitExpression(v.initializer!);
    var body = _visitExpression(node.body);
    var temp = _tempVariables.remove(v);
    if (temp != null) {
      if (_letVariables != null) {
        init = js_ast.Assignment(temp, init);
        _letVariables!.add(temp);
      } else {
        // TODO(jmesserly): make sure this doesn't happen on any performance
        // critical call path.
        //
        // Annotations on a top-level, non-lazy function type should be the only
        // remaining use.
        var arrowFunction = js_ast.ArrowFun([temp], body);
        final asyncAnalysis = PreTranslationAnalysis((node) {
          throw UnsupportedError('Unknown node in block expression: $node');
        }, arrowFunction)
          ..analyze();
        final isAsyncIife = asyncAnalysis.hasAwaitOrYield.contains(body);
        if (isAsyncIife) {
          final transformedFunction = _rewriteAsyncFunction(
              js_ast.Fun([temp], js_ast.Block([js_ast.Return(body)])),
              AsyncMarker.Async,
              null,
              node.getStaticType(_staticTypeContext),
              functionBody: _toSourceLocation(node.fileOffset),
              functionEnd: _toSourceLocation(node.fileOffset));
          arrowFunction = js_ast.ArrowFun([temp], transformedFunction.body);
        }
        final call = js_ast.Call(arrowFunction, [init]);
        return isAsyncIife ? js_ast.Await(call) : call;
      }
    }
    return js_ast.Binary(',', init, body);
  }

  @override
  js_ast.Expression visitBlockExpression(BlockExpression node) {
    var jsExpr = _visitExpression(node.value);
    var jsStmts = [
      for (var s in node.body.statements) _visitStatement(s),
      js_ast.Return(jsExpr),
    ];
    final statementBlock = js_ast.Block(jsStmts);
    var arrowFunction = js_ast.ArrowFun(const [], statementBlock);
    final asyncAnalysis = PreTranslationAnalysis((node) {
      throw UnsupportedError(
          'Unknown node in block expression: $node (${node.runtimeType}, '
          '${node.sourceInformation})');
    }, arrowFunction)
      ..analyze();
    final isAsyncIife = asyncAnalysis.hasAwaitOrYield.contains(statementBlock);
    if (isAsyncIife) {
      final transformedFunction = _rewriteAsyncFunction(
          js_ast.Fun(const [], statementBlock),
          AsyncMarker.Async,
          null,
          node.getStaticType(_staticTypeContext),
          functionBody: _toSourceLocation(node.fileOffset),
          functionEnd: _toSourceLocation(node.fileOffset));
      arrowFunction = js_ast.ArrowFun(const [], transformedFunction.body);
    }
    final call = js_ast.Call(arrowFunction, const []);
    return isAsyncIife ? js_ast.Await(call) : call;
  }

  @override
  js_ast.Expression visitInstantiation(Instantiation node) {
    return _runtimeCall('gbind(#, #)', [
      _visitExpression(node.expression),
      node.typeArguments.map(_emitType).toList()
    ]);
  }

  @override
  js_ast.Expression visitLoadLibrary(LoadLibrary node) =>
      _runtimeCall('loadLibrary(#, #, #)', [
        js.string(node.import.enclosingLibrary.importUri.toString()),
        js.string(node.import.name!),
        js.string(
            _libraryToModule(node.import.targetLibrary, throwIfNotFound: false))
      ]);

  // TODO(jmesserly): DDC loads all libraries eagerly.
  // See
  // https://github.com/dart-lang/sdk/issues/27776
  // https://github.com/dart-lang/sdk/issues/27777
  @override
  js_ast.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
      _runtimeCall('checkDeferredIsLoaded(#, #)', [
        js.string(node.import.enclosingLibrary.importUri.toString()),
        js.string(node.import.name!)
      ]);

  bool _reifyFunctionType(FunctionNode f) {
    var parent = f.parent;
    if (parent is FunctionDeclaration &&
        (isLateLoweredLocalGetter(parent.variable) ||
            isLateLoweredLocalSetter(parent.variable))) {
      // Late local variables are lowered to local get and set functions.
      // These functions should never need to be tagged with their types.
      return false;
    }
    if (!_currentLibrary!.importUri.isScheme('dart')) return true;

    // SDK libraries can skip reification if they request it.
    bool reifyFunctionTypes(Expression a) =>
        isBuiltinAnnotation(a, '_js_helper', 'ReifyFunctionTypes');
    while (parent != null) {
      var a = findAnnotation(parent, reifyFunctionTypes);
      if (a != null) {
        var value = _constants.getFieldValueFromAnnotation(a, 'value');
        if (value is bool) return value;
      }
      parent = parent.parent;
    }
    return true;
  }

  bool _reifyTearoff(Member member) {
    return member is Procedure &&
        !member.isAccessor &&
        !member.isFactory &&
        !(_isInForeignJS && _isBuildingSdk) &&
        !usesJSInterop(member) &&
        _reifyFunctionType(member.function);
  }

  /// Returns the name value of the `JSExportName` annotation (when compiling
  /// the SDK), or `null` if there's none. This is used to control the name
  /// under which functions are compiled and exported.
  String? _jsExportName(NamedNode n) {
    var library = getLibrary(n);
    if (!library.importUri.isScheme('dart')) return null;

    return _annotationName(n, isJSExportNameAnnotation);
  }

  /// If [node] has annotation matching [test] and the first argument is a
  /// string, this returns the string value.
  ///
  /// Calls [findAnnotation] followed by [getNameFromAnnotation].
  String? _annotationName(NamedNode node, bool Function(Expression) test) {
    var annotation = findAnnotation(node, test);
    return annotation != null
        ? _constants.getFieldValueFromAnnotation(annotation, 'name') as String?
        : null;
  }

  @override
  js_ast.Expression visitConstant(Constant node) {
    if (node is StaticTearOffConstant) {
      // JS() or external JS consts should not be lazily loaded.
      var isSdk = node.target.enclosingLibrary.importUri.isScheme('dart');
      if (_isInForeignJS) {
        return _emitStaticTarget(node.target);
      }
      if (node.target.isExternal && !isSdk) {
        return _runtimeCall('tearoffInterop(#, #)', [
          _emitStaticTarget(node.target),
          js.boolean(_isNullCheckableJsInterop(node.target))
        ]);
      }
    }
    if (node is TypeLiteralConstant) {
      // We bypass the use of constants, since types are already canonicalized
      // in the DDC output. DDC emits type literals in two contexts:
      //   * Foreign JS functions: we use the non-nullable version of some types
      //     directly in the runtime libraries (e.g. dart:_runtime). For
      //     correctness of those libraries, we need to remove the legacy marker
      //     that was added by the CFE normalization of type literals.
      //
      //   * Regular user code: we need to emit a canonicalized type. We do so
      //     by calling `wrapType` on the type at runtime. By emitting the
      //     non-nullable version we save some redundant work at runtime.
      //     Technically, emitting a legacy type in this case would be correct,
      //     only more verbose and inefficient.
      var type = node.type;
      if (type.nullability == Nullability.legacy) {
        type = type.withDeclaredNullability(Nullability.nonNullable);
      }
      assert(!_isInForeignJS ||
          type.nullability == Nullability.nonNullable ||
          // The types dynamic, void, and Null all intrinsically have
          // `Nullability.nullable` but are handled explicitly without emitting
          // the nullable runtime wrapper. They are safe to allow through
          // unchanged.
          type == const DynamicType() ||
          type == const NullType() ||
          type == const VoidType());
      return _emitTypeLiteral(type);
    }
    if (node is PrimitiveConstant) {
      return super.visitConstant(node);
    }

    // Avoid caching constants during evaluation while scoping issues remain.
    // See: #44713
    if (_constTableCache.incrementalMode) {
      return super.visitConstant(node);
    }

    var constAlias = _constAliasCache[node];
    if (constAlias != null) {
      return constAlias;
    }
    var constAliasString = 'C${_constAliasCache.length}';
    var constAliasProperty = _propertyName(constAliasString);

    _constTableCache[constAliasString] = js.call('void 0');
    var constAliasAccessor = _constTableCache.access(constAliasString);

    var constAccessor = js.call(
        '# || #.#', [constAliasAccessor, _constTable, constAliasProperty]);
    _constAliasCache[node] = constAccessor;
    var constJs = super.visitConstant(node);

    var func = js_ast.Fun(
        [],
        js_ast.Block([
          js.statement('return # = #;', [constAliasAccessor, constJs])
        ]));
    var accessor = js_ast.Method(constAliasProperty, func, isGetter: true);
    _constLazyAccessors.add(accessor);
    return constAccessor;
  }

  @override
  js_ast.Expression visitNullConstant(NullConstant node) =>
      js_ast.LiteralNull();
  @override
  js_ast.Expression visitBoolConstant(BoolConstant node) =>
      js.boolean(node.value);
  @override
  js_ast.Expression visitIntConstant(IntConstant node) => js.number(node.value);
  @override
  js_ast.Expression visitDoubleConstant(DoubleConstant node) {
    var value = node.value;

    // Emit the constant as an integer, if possible.
    if (value.isFinite) {
      var intValue = value.toInt();
      const minInt32 = -0x80000000;
      const maxInt32 = 0x7FFFFFFF;
      if (intValue.toDouble() == value &&
          intValue >= minInt32 &&
          intValue <= maxInt32) {
        return js.number(intValue);
      }
    }
    if (value.isInfinite) {
      if (value.isNegative) {
        return js.call('-1 / 0');
      }
      return js.call('1 / 0');
    }
    if (value.isNaN) {
      return js.call('0 / 0');
    }
    return js.number(value);
  }

  @override
  js_ast.Expression visitStringConstant(StringConstant node) =>
      js.escapedString(node.value, '"');

  // DDC does not currently use the non-primitive constant nodes; rather these
  // are emitted via their normal expression nodes.
  @override
  js_ast.Expression defaultConstant(Constant node) => _emitInvalidNode(node);

  @override
  js_ast.Expression visitSymbolConstant(SymbolConstant node) =>
      _emitDartSymbol(node.name);

  @override
  js_ast.Expression visitMapConstant(MapConstant node) {
    var entries = [
      for (var e in node.entries) ...[
        visitConstant(e.key),
        visitConstant(e.value),
      ],
    ];
    return _emitConstMap(node.keyType, node.valueType, entries);
  }

  @override
  js_ast.Expression visitListConstant(ListConstant node) => _emitConstList(
      node.typeArgument, node.entries.map(visitConstant).toList());

  @override
  js_ast.Expression visitSetConstant(SetConstant node) => _emitConstSet(
      node.typeArgument, node.entries.map(visitConstant).toList());

  @override
  js_ast.Expression visitRecordConstant(RecordConstant node) {
    // RecordConstant names are already sorted alphabetically in kernel.
    var names = node.named.keys;
    var positionalElementCount = node.positional.length;
    var shapeKey = _recordShapeKey(positionalElementCount, names);
    return _runtimeCall('recordLiteral(#, #, #, [#])', [
      js.string(shapeKey),
      js.number(positionalElementCount),
      names.isEmpty ? js.call('void 0') : js.stringArray(names),
      [
        ...node.positional.map(visitConstant),
        ...node.named.values.map(visitConstant)
      ]
    ]);
  }

  @override
  js_ast.Expression visitInstanceConstant(InstanceConstant node) {
    _declareBeforeUse(node.classNode);
    var savedTypeEnvironment = _currentTypeEnvironment;
    if (node.classNode.typeParameters.isNotEmpty) {
      _currentTypeEnvironment =
          ClassTypeEnvironment(node.classNode.typeParameters);
    }

    js_ast.Property entryToProperty(MapEntry<Reference, Constant> entry) {
      var constant = visitConstant(entry.value);
      var member = entry.key.asField;
      var cls = member.enclosingClass!;
      // Enums cannot be overridden, so we can safely use the field name
      // directly.  Otherwise, use a private symbol in case the field
      // was overridden.
      var symbol = cls.isEnum
          ? _emitMemberName(member.name.text, member: member)
          : _getSymbol(_emitClassPrivateNameSymbol(
              cls.enclosingLibrary, getLocalClassName(cls), member));
      return js_ast.Property(symbol, constant);
    }

    // Non-nullable is forced here because the type of an instance constant
    // should never appear as legacy "*" at runtime but the library where the
    // constant is defined can cause those types to appear here.
    var type = node
        .getType(_staticTypeContext)
        .withDeclaredNullability(Nullability.nonNullable);
    var classRef = _emitClassRef(type as InterfaceType);
    var prototype = js.call('#.prototype', [classRef]);
    var properties = [
      if (type.typeArguments.isNotEmpty)
        // Generic interface type instances require a type information tag.
        js_ast.Property(
            _propertyName(js_ast.FixedNames.rtiName), _emitType(type)),
      for (var e in node.fieldValues.entries.toList().reversed)
        entryToProperty(e),
    ];
    var constant = _canonicalizeConstObject(_emitJSObjectSetPrototypeOf(
        js_ast.ObjectInitializer(properties, multiline: true), prototype,
        fullyQualifiedName: false));
    _currentTypeEnvironment = savedTypeEnvironment;
    return constant;
  }

  /// Emits a private name JS Symbol for [member] unique to a Dart class
  /// [className].
  ///
  /// This is now required for fields of constant objects that may be overridden
  /// within the same library.
  js_ast.ScopedId _emitClassPrivateNameSymbol(
      Library library, String className, Member member,
      [js_ast.ScopedId? id]) {
    var name = '$className.${member.name.text}';
    // Wrap the name as a symbol here so it matches what you would find at
    // runtime when you get all properties and symbols from an instance.
    memberNames[member] = 'Symbol($name)';
    return _emitPrivateNameSymbol(library, name, id);
  }

  @override
  js_ast.Expression visitStaticTearOffConstant(StaticTearOffConstant node) {
    _declareBeforeUse(node.target.enclosingClass);
    return _emitStaticGet(node.target);
  }

  @override
  js_ast.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
      _emitTypeLiteral(node.type);

  @override
  js_ast.Expression visitInstantiationConstant(InstantiationConstant node) =>
      _canonicalizeConstObject(_runtimeCall('gbind(#, #)', [
        visitConstant(node.tearOffConstant),
        node.types.map(_emitType).toList()
      ]));

  @override
  js_ast.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
      throw UnsupportedError('Encountered an unevaluated constant: $node');

  @override
  js_ast.Expression visitFunctionTearOff(FunctionTearOff node) {
    var receiver = node.receiver;
    var receiverType = receiver.getStaticType(_staticTypeContext);
    var jsReceiver = _visitExpression(receiver);
    if (receiverType is InterfaceType &&
        receiverType.classNode == _coreTypes.functionClass) {
      // Historically DDC has treated this case as a dynamic get and allowed it
      // to evaluate at runtime.
      //
      // This is here to preserve the existing behavior for the non-static
      // JavaScript interop (including some failing cases) but could potentially
      // be cleaned up as a breaking change.
      return _runtimeCall(
          'dload$_replSuffix(#, #)', [jsReceiver, js.string('call')]);
    }
    // Otherwise, tearoff of `call` on a function type is a no-op.
    return jsReceiver;
  }

  /// Creates header comments with helpful compilation information.
  List<js_ast.Comment> _generateCompilationHeader() {
    var headerOptions = [
      if (_options.canaryFeatures) 'canary',
      if (_options.emitLibraryBundle) 'emitLibraryBundle',
      'soundNullSafety(${_options.soundNullSafety})',
      'enableAsserts(${_options.enableAsserts})',
    ];
    var enabledExperiments = <String>[];
    _options.experiments.forEach((key, value) {
      if (value) enabledExperiments.add(key);
    });
    var header = [
      js_ast.Comment(
          'Generated by DDC, the Dart Development Compiler (to JavaScript).'),
      js_ast.Comment('Version: ${io.Platform.version}'),
      js_ast.Comment('Module: ${_options.moduleName}'),
      js_ast.Comment('Flags: ${headerOptions.join(', ')}'),
      if (enabledExperiments.isNotEmpty)
        js_ast.Comment('Experiments: ${enabledExperiments.join(', ')}')
    ];
    return header;
  }

  @override
  js_ast.Statement visitIfCaseStatement(IfCaseStatement node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError('ProgramCompiler.visitIfCaseStatement');
  }

  @override
  js_ast.Expression visitPatternAssignment(PatternAssignment node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError('ProgramCompiler.visitPatternAssignment');
  }

  @override
  js_ast.Statement visitPatternSwitchStatement(PatternSwitchStatement node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError('ProgramCompiler.visitPatternSwitchStatement');
  }

  @override
  js_ast.Statement visitPatternVariableDeclaration(
      PatternVariableDeclaration node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError('ProgramCompiler.visitPatternVariableDeclaration');
  }

  @override
  js_ast.Expression visitSwitchExpression(SwitchExpression node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError('ProgramCompiler.visitSwitchExpression');
  }

  @override
  js_ast.Expression visitAuxiliaryExpression(AuxiliaryExpression node) {
    throw UnsupportedError(
        'Unsupported auxiliary expression $node (${node.runtimeType}).');
  }

  @override
  js_ast.Statement visitAuxiliaryStatement(AuxiliaryStatement node) {
    throw UnsupportedError(
        'Unsupported auxiliary statement $node (${node.runtimeType}).');
  }

  /// Adds an import mapping from [library] to [id].
  ///
  /// This is a temporary work around until imports can be manually added in
  /// `startModule()`.
  void _forceLibraryImport(Library library, js_ast.ScopedId id) {
    _imports[library] = id;
  }

  void _setEmitIfIncrementalLibrary(Library library) {
    if (_incrementalMode) {
      _setEmitIfIncremental(_libraryToModule(library), _jsLibraryName(library));
    }
  }

  void _setEmitIfIncremental(String module, String library) {
    if (_incrementalMode) {
      _incrementalModules.putIfAbsent(module, () => {}).add(library);
    }
  }

  /// When compiling the body of a `operator []=` method, this will be non-null
  /// and will indicate the value that should be returned from any `return;`
  /// statements.
  js_ast.Identifier? get _operatorSetResult {
    var stack = _operatorSetResultStack;
    return stack.isEmpty ? null : stack.last;
  }

  /// Called when starting to emit methods/functions, in particular so we can
  /// implement special handling of the user-defined `[]=` and `==` methods.
  ///
  /// See also [_exitFunction] and [_emitReturnStatement].
  void _enterFunction(String? name, List<js_ast.Parameter> formals,
      bool Function() isLastParamMutated) {
    if (name == '[]=') {
      _operatorSetResultStack.add(isLastParamMutated()
          ? js_ast.ScopedId((formals.last as js_ast.Identifier).name)
          : formals.last as js_ast.Identifier);
    } else {
      _operatorSetResultStack.add(null);
    }
  }

  /// Called when finished emitting methods/functions, and must correspond to a
  /// previous [_enterFunction] call.
  js_ast.Block _exitFunction(
      List<js_ast.Parameter> formals, js_ast.Block code) {
    var setOperatorResult = _operatorSetResultStack.removeLast();
    if (setOperatorResult != null) {
      // []= methods need to return the value. We could also address this at
      // call sites, but it's less code size to handle inside the operator.
      var valueParam = formals.last;
      var statements = code.statements;
      if (statements.isEmpty || !statements.last.alwaysReturns) {
        statements.add(js_ast.Return(setOperatorResult));
      }
      if (!identical(setOperatorResult, valueParam)) {
        // If the value parameter was mutated, then we use a temporary
        // variable to track the initial value
        formals.last = setOperatorResult;
        code = js
            .block('{ let # = #; #; }', [valueParam, setOperatorResult, code]);
      }
    }
    return code;
  }

  /// Emits a return statement `return <value>;`, handling special rules for
  /// the `operator []=` method.
  js_ast.Statement _emitReturnStatement(js_ast.Expression? value) {
    if (_operatorSetResult != null) {
      var result = js_ast.Return(_operatorSetResult);
      return value != null
          ? js_ast.Block([value.toStatement(), result])
          : result;
    }
    return value != null ? value.toReturn() : js_ast.Return();
  }

  /// Prepends the `dart.` and then uses [js.call] to parse the specified JS
  /// [code] template, passing [args].
  ///
  /// For example:
  ///
  ///     _runtimeCall('asInt(#)', [<expr>])
  ///
  /// Generates a JS AST representing:
  ///
  ///     dart.asInt(<expr>)
  ///
  js_ast.Expression _runtimeCall(String code, [List<Object>? args]) {
    _setEmitIfIncremental(_libraryToModule(_coreLibrary), _runtimeModule.name);
    return js.call('#.$code', <Object>[_runtimeModule, ...?args]);
  }

  /// Calls [_runtimeCall] and uses `toStatement()` to convert the resulting
  /// expression into a statement.
  js_ast.Statement _runtimeStatement(String code, [List<Object>? args]) =>
      _runtimeCall(code, args).toStatement();

  /// Emits a private name JS Symbol for [name] scoped to the Dart [library].
  ///
  /// If the same name is used in multiple libraries in the same module,
  /// distinct symbols will be used, so each library will have distinct private
  /// member names, that won't collide at runtime, as required by the Dart
  /// language spec.
  ///
  /// If an [id] is provided, try to use that.
  ///
  /// TODO(vsm): Clean up id generation logic.  This method is used to both
  /// define new symbols and to reference existing ones.  If it's called
  /// multiple times with same [library] and [name], we'll allocate redundant
  /// top-level variables (see callers to this method).
  js_ast.ScopedId _emitPrivateNameSymbol(Library library, String name,
      [js_ast.ScopedId? id]) {
    /// Initializes the JS `Symbol` for the private member [name] in [library].
    ///
    /// If the library is in the current JS module ([_libraries] contains it),
    /// the private name will be created and exported. The exported symbol is
    /// used for a few things:
    ///
    /// - private fields of constant objects
    /// - stateful hot reload (not yet implemented)
    /// - correct library scope in REPL (not yet implemented)
    ///
    /// If the library is imported, then the existing private name will be
    /// retrieved from it. In both cases, we use the same `dart.privateName`
    /// runtime call.
    js_ast.ScopedId initPrivateNameSymbol() {
      var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
      idName = idName.replaceAll(js_ast.invalidCharInIdentifier, '_');
      var identifier = id ?? js_ast.ScopedId(idName);
      _addSymbol(
          identifier,
          _runtimeCall('privateName(#, #)',
              [_emitLibraryName(library), js.string(name)]));
      if (!_containerizeSymbols) {
        // TODO(vsm): Change back to `const`.
        // See https://github.com/dart-lang/sdk/issues/40380.
        _moduleItems.add(js.statement('var # = #', [
          identifier,
          _runtimeCall(
              'privateName(#, #)', [_emitLibraryName(library), js.string(name)])
        ]));
      }
      return identifier;
    }

    var privateNames = _privateNames.putIfAbsent(library, () => HashMap());
    var symbolId = privateNames.putIfAbsent(name, initPrivateNameSymbol);

    _setEmitIfIncrementalLibrary(library);
    _setEmitIfIncremental(_libraryToModule(_coreLibrary), _runtimeModule.name);
    _symbolContainer.setEmitIfIncremental(symbolId);

    return symbolId;
  }

  /// Emits an expression to set the property [nameExpr] on the class [className],
  /// with [value].
  ///
  /// This will use `className.name = value` if possible, otherwise it will use
  /// `dart.defineValue(className, name, value)`. This is required when
  /// `FunctionNode.prototype` already defines a getters with the same name.
  js_ast.Expression _defineValueOnClass(Class c, js_ast.Expression className,
      js_ast.Expression nameExpr, js_ast.Expression value) {
    var args = [className, nameExpr, value];
    if (nameExpr is js_ast.LiteralString) {
      var name = nameExpr.valueWithoutQuotes;
      if (js_ast.isFunctionPrototypeGetter(name) ||
          _superclassHasStatic(c, name)) {
        return _runtimeCall('defineValue(#, #, #)', args);
      }
    }
    return js.call('#.# = #', args);
  }

  /// Emits a Dart Symbol with the given member [symbolName].
  ///
  /// If the symbol refers to a private name, its library will be set to the
  /// [currentLibrary], so the Symbol is scoped properly.
  js_ast.Expression _emitDartSymbol(String symbolName) {
    // TODO(vsm): Handle qualified symbols correctly.
    var last = symbolName.split('.').last;
    var name = js.escapedString(symbolName, "'");
    js_ast.Expression result;
    if (last.startsWith('_')) {
      var nativeSymbolAccessor =
          _getSymbol(_emitPrivateNameSymbol(_currentLibrary!, last));
      result = js.call('new #.new(#, #)', [
        _emitConstructorAccess(_privateSymbolType),
        name,
        nativeSymbolAccessor
      ]);
    } else {
      result = js.call(
          'new #.new(#)', [_emitConstructorAccess(_internalSymbolType), name]);
    }
    return _canonicalizeConstObject(result);
  }

  /// Calls the `dart.const` function in "dart:_runtime" to canonicalize a
  /// constant instance of a user-defined class stored in [expr].
  js_ast.Expression _canonicalizeConstObject(js_ast.Expression expr) =>
      _runtimeCall('const(#)', [expr]);

  /// Emits preamble for the module containing [libraries], and returns the
  /// list of module items for further items to be added.
  ///
  /// The preamble consists of initializing the identifiers for each library,
  /// that will be used to store their members. It also generates the
  /// appropriate ES6 `export` declaration to export them from this module.
  ///
  /// After the code for all of the library members is emitted,
  /// [_emitImportsAndExtensionSymbols] should be used to emit imports/extension
  /// symbols into the list returned by this method. Finally, [_finishModule]
  /// can be called to complete the module and return the resulting JS AST.
  ///
  /// This also initializes several fields: [_runtimeModule],
  /// [_extensionSymbolsModule], and the [_libraries] map needed by
  /// [_emitLibraryName].
  List<js_ast.ModuleItem> _startModule(Iterable<Library> libraries) {
    if (_isBuildingSdk) {
      // Don't allow these to be renamed when we're building the SDK.
      // There is JS code in dart:* that depends on their names.
      _runtimeModule = js_ast.Identifier('dart');
      _extensionSymbolsModule = js_ast.Identifier('dartx');
    } else {
      // Otherwise allow these to be renamed so users can write them.
      _runtimeModule = js_ast.ScopedId('dart');
      _extensionSymbolsModule = js_ast.ScopedId('dartx');
    }

    // Initialize our library variables.
    var items = <js_ast.ModuleItem>[];
    var exports = <js_ast.NameSpecifier>[];

    if (_isBuildingSdk) {
      // Bootstrap the ability to create Dart library objects.
      var libraryProto = js_ast.ScopedId('_library');
      items.add(js.statement('const # = Object.create(null)', libraryProto));
      items.add(js.statement(
          'const # = Object.create(#)', [_runtimeModule, libraryProto]));
      items.add(js.statement('#.library = #', [_runtimeModule, libraryProto]));
      exports.add(js_ast.NameSpecifier(_runtimeModule));
    }
    for (var library in libraries) {
      if (_isBuildingSdk && _isSdkInternalRuntime(library)) {
        _libraries[library] = _runtimeModule;
        continue;
      }
      var libraryId = _isBuildingSdk && _isDartLibrary(library, '_rti')
          ? _rtiLibraryId
          : js_ast.ScopedId(_jsLibraryName(library));

      _libraries[library] = libraryId;
      var alias = _jsLibraryAlias(library);
      var aliasId = alias == null ? null : js_ast.ScopedId(alias);

      // TODO(vsm): Change back to `const`.
      // See https://github.com/dart-lang/sdk/issues/40380.
      items.add(js.statement(
          'var # = Object.create(#.library)', [libraryId, _runtimeModule]));
      exports.add(js_ast.NameSpecifier(libraryId, asName: aliasId));
    }

    // dart:_runtime has a magic module that holds extension method symbols.
    // TODO(jmesserly): find a cleaner design for this.
    if (_isBuildingSdk) {
      var id = _extensionSymbolsModule;
      // TODO(vsm): Change back to `const`.
      // See https://github.com/dart-lang/sdk/issues/40380.
      items.add(js
          .statement('var # = Object.create(#.library)', [id, _runtimeModule]));
      exports.add(js_ast.NameSpecifier(id));
    }
    items.add(js_ast.ExportDeclaration(js_ast.ExportClause(exports)));

    if (_isBuildingSdk) {
      // Initialize the private name function.
      // To bootstrap the SDK, this needs to be emitted before other code.
      var symbol = js_ast.ScopedId('_privateNames');
      items.add(js.statement('const # = Symbol("_privateNames")', symbol));
      items.add(_runtimeStatement(r'''
        privateName = function(library, name) {
          let names = library[#];
          if (names == null) names = library[#] = new Map();
          let symbol = names.get(name);
          if (symbol == null) names.set(name, symbol = Symbol(name));
          return symbol;
        }
      ''', [symbol, symbol]));
    }

    return items;
  }

  /// Returns the canonical name to refer to the Dart library.
  js_ast.Identifier _emitLibraryName(Library library) {
    _setEmitIfIncrementalLibrary(library);

    // Avoid adding the dart:_runtime to _imports when our runtime unit tests
    // import it explicitly. It will always be implicitly imported.
    if (_isSdkInternalRuntime(library)) return _runtimeModule;

    // It's either one of the libraries in this module, or it's an import.
    return _libraries[library] ??
        _imports.putIfAbsent(
            library, () => js_ast.ScopedId(_jsLibraryName(library)));
  }

  /// Emits imports into [items].
  void _emitImports(List<js_ast.ModuleItem> items) {
    var modules = <String, List<Library>>{};
    for (var import in _imports.keys) {
      modules.putIfAbsent(_libraryToModule(import), () => []).add(import);
    }

    String? coreModuleName;
    if (!_libraries.containsKey(_coreLibrary)) {
      coreModuleName = _libraryToModule(_coreLibrary);
    }

    modules.forEach((module, libraries) {
      if (!_incrementalMode || _incrementalModules.containsKey(module)) {
        var usedLibraries = _incrementalModules[module];

        // Generate import directives.
        //
        // Our import variables are temps and can get renamed. Since our renaming
        // is integrated into js_ast, it is aware of this possibility and will
        // generate an "as" if needed. For example:
        //
        //     import {foo} from 'foo';         // if no rename needed
        //     import {foo as foo$} from 'foo'; // if rename was needed
        //
        var imports = <js_ast.NameSpecifier>[];
        for (var library in libraries) {
          if (!_incrementalMode ||
              usedLibraries!.contains(_jsLibraryName(library))) {
            var alias = _jsLibraryAlias(library);
            if (alias != null) {
              var aliasId = js_ast.ScopedId(alias);
              imports.add(
                  js_ast.NameSpecifier(aliasId, asName: _imports[library]));
            } else {
              imports.add(js_ast.NameSpecifier(_imports[library]));
            }
          }
        }

        if (module == coreModuleName) {
          if (!_incrementalMode ||
              usedLibraries!.contains(_runtimeModule.name)) {
            imports.add(js_ast.NameSpecifier(_runtimeModule));
          }
          if (!_incrementalMode ||
              usedLibraries!.contains(_extensionSymbolsModule.name)) {
            imports.add(js_ast.NameSpecifier(_extensionSymbolsModule));
          }
        }

        if (!_incrementalMode || imports.isNotEmpty) {
          items.add(js_ast.ImportDeclaration(
              namedImports: imports, from: js.string(module, "'")));
        }
      }
    });
  }

  /// Emits extension methods into [items].
  void _emitExtensionSymbols(List<js_ast.ModuleItem> items,
      {bool forceExtensionSymbols = false}) {
    // Initialize extension symbols
    _extensionSymbols.forEach((name, id) {
      js_ast.Expression value =
          js_ast.PropertyAccess(_extensionSymbolsModule, _propertyName(name));
      if (_isBuildingSdk) {
        value = js.call('# = Symbol(#)', [value, js.string('dartx.$name')]);
      } else if (forceExtensionSymbols) {
        value = js.call(
            '# || (# = Symbol(#))', [value, value, js.string('dartx.$name')]);
      }
      // Emit hoisted extension symbols that are marked as noEmit in regular as
      // well as incremental mode (if needed) since they are going to be
      // referenced as such in the generated expression.
      if (!_incrementalMode ||
          _symbolContainer.incrementalModuleItems.contains(id)) {
        if (!_symbolContainer.canEmit(id)) {
          // Extension symbols marked with noEmit are managed manually.
          // TODO(vsm): Change back to `const`.
          // See https://github.com/dart-lang/sdk/issues/40380.
          items.add(js.statement('var # = #;', [id, value]));
        }
      }
      if (_symbolContainer.incrementalModuleItems.contains(id)) {
        _setEmitIfIncremental(
            _libraryToModule(_coreLibrary), _extensionSymbolsModule.name);
      }
      _symbolContainer[id] = value;
    });
  }

  /// Emits exports as imports into [items].
  ///
  /// Use information from exports to re-define library variables referenced
  /// inside compiled expressions in incremental mode. That matches importing
  /// a current module into the symbol used to represent the library during
  /// original compilation in [ProgramCompiler.emitModule].
  ///
  /// Example of exports emitted to JavaScript during emitModule:
  ///
  /// ```
  /// dart.trackLibraries("web/main", { ... });
  /// // Exports:
  /// return {
  ///  web__main: main
  /// };
  /// ```
  ///
  /// The transformation to imports during expression compilation converts the
  /// exports above to:
  ///
  /// ```
  /// const web__main = require('web/main');
  /// const main = web__main.web__main;
  /// ```
  ///
  /// Where the compiled expression references `main`.
  void _emitExportsAsImports(List<js_ast.ModuleItem> items, Library current) {
    var exports = <js_ast.NameSpecifier>[];
    assert(_incrementalMode);
    assert(!_isBuildingSdk);

    var module = _libraryToModule(current);
    var usedLibraries = _incrementalModules[module] ?? {};

    if (usedLibraries.isNotEmpty) {
      _libraries.forEach((library, libraryId) {
        if (usedLibraries.contains(_jsLibraryName(library))) {
          var alias = _jsLibraryAlias(library);
          var aliasId = alias == null ? libraryId : js_ast.ScopedId(alias);
          var asName = alias == null ? null : libraryId;
          exports.add(js_ast.NameSpecifier(aliasId, asName: asName));
        }
      });

      items.add(js_ast.ImportDeclaration(
          namedImports: exports, from: js.string(module, "'")));
    }
  }

  /// Emits imports and extension methods into [items].
  void _emitImportsAndExtensionSymbols(List<js_ast.ModuleItem> items,
      {bool forceExtensionSymbols = false}) {
    _emitImports(items);
    _emitExtensionSymbols(items, forceExtensionSymbols: forceExtensionSymbols);
  }

  void _emitDebuggerExtensionInfo(String name) {
    var properties = <js_ast.Property>[];
    var parts = <js_ast.Property>[];
    _libraries.forEach((library, value) {
      // TODO(jacobr): we could specify a short library name instead of the
      // full library uri if we wanted to save space.
      var libraryName = js.escapedString(_jsLibraryDebuggerName(library));
      properties.add(js_ast.Property(libraryName, value));

      // Dynamic modules shouldn't define a library that was previously defined.
      // We leverage that we track which libraries have been defined via
      // `trackedLibraries` to query whether a library already exists.
      if (_options.dynamicModule) {
        _moduleItems.add(js.statement('''if (# != null) {
                throw Error(
                    "Dynamic module provides second definition for " + #);
            }''', [
          _runtimeCall('getLibrary(#)', [libraryName]),
          libraryName
        ]));
      }

      var partNames = _jsPartDebuggerNames(library);
      if (partNames.isNotEmpty) {
        parts.add(js_ast.Property(libraryName, js.stringArray(partNames)));
      }
    });
    var module = js_ast.ObjectInitializer(properties, multiline: true);
    var partMap = js_ast.ObjectInitializer(parts, multiline: true);

    // Track the module name for each library in the module.
    // This data is mainly consumed by the debugger and by the stack trace
    // mapper. It is also used for the experimental dynamic modules feature
    // to validate that a dynamic module doesn't reintroduce an existing
    // library.
    //
    // See also the implementation of this API in the SDK.
    _moduleItems.add(_runtimeStatement(
        'trackLibraries(#, #, #, $sourceMapLocationID)',
        [js.string(name), module, partMap]));
  }

  /// Returns an accessor for [id] via the symbol container.
  /// E.g., transforms $sym to S$5.$sym.
  ///
  /// A symbol lookup on an id marked no emit omits the symbol accessor.
  js_ast.Expression _getSymbol(js_ast.Identifier id) {
    _symbolContainer.setEmitIfIncremental(id);
    return _symbolContainer.canEmit(id) ? _symbolContainer.access(id) : id;
  }

  /// Returns the raw JS value associated with [id].
  js_ast.Expression _getSymbolValue(js_ast.Identifier id) {
    _symbolContainer.setEmitIfIncremental(id);
    return _symbolContainer[id]!;
  }

  /// Inserts a symbol into the symbol table.
  js_ast.Expression _addSymbol(js_ast.Identifier id, js_ast.Expression symbol) {
    _symbolContainer[id] = symbol;
    _symbolContainer.setEmitIfIncremental(id);
    if (!_containerizeSymbols) {
      _symbolContainer.setNoEmit(id);
    }
    return _symbolContainer[id]!;
  }

  /// Finishes the module created by [_startModule], by combining the preamble
  /// [items] with the [_moduleItems] that have been emitted.
  ///
  /// The [moduleName] should specify the module's name, and the items should
  /// be the list resulting from startModule, with additional items added,
  /// but not including the contents of [_moduleItems] (which will be handled
  /// by this method itself).
  ///
  /// Note, this function mutates the items list and returns it as the `body`
  /// field of the result.
  js_ast.Program _finishModule(List<js_ast.ModuleItem> items, String moduleName,
      {List<js_ast.Comment> header = const []}) {
    // TODO(jmesserly): there's probably further consolidation we can do
    // between DDC's two backends, by moving more code into this method, as the
    // code between `startModule` and `finishModule` is very similar in both.
    _emitDebuggerExtensionInfo(moduleName);

    // Emit all top-level JS symbol containers.
    items.addAll(_symbolContainer.emit());

    if (_dynamicEntrypoint != null) {
      // Expose the entrypoint of the dynamic module under a reserved name.
      // TODO(sigmund): this could use a reserved symbol from dartx.
      var name = _emitTopLevelName(_dynamicEntrypoint!);
      _moduleItems.add(js_ast.ExportDeclaration(
          js('var __dynamic_module_entrypoint__ = #', [name])));
    }

    // Add the module's code (produced by visiting compilation units, above)
    _copyAndFlattenBlocks(items, _moduleItems);
    _moduleItems.clear();

    // Build the module.
    return js_ast.Program(items, name: moduleName, header: header);
  }

  /// Flattens blocks in [items] to a single list.
  ///
  /// This will not flatten blocks that are marked as being scopes.
  void _copyAndFlattenBlocks(
      List<js_ast.ModuleItem> result, Iterable<js_ast.ModuleItem> items) {
    for (var item in items) {
      if (item is js_ast.Block && !item.isScope) {
        _copyAndFlattenBlocks(result, item.statements);
      } else {
        result.add(item);
      }
    }
  }

  /// This is an internal method used by [_emitMemberName] and the
  /// optimized `dart:_runtime extensionSymbol` builtin to get the symbol
  /// for `dartx.<name>`.
  ///
  /// Do not call this directly; you want [_emitMemberName], which knows how to
  /// handle the many details involved in naming.
  js_ast.ScopedId _getExtensionSymbolInternal(String name) {
    if (!_extensionSymbols.containsKey(name)) {
      var id = js_ast.ScopedId(
          '\$${js_ast.friendlyNameForDartOperator[name] ?? name}');
      _extensionSymbols[name] = id;
      _addSymbol(id, id);
    }
    var symbolId = _extensionSymbols[name]!;
    _symbolContainer.setEmitIfIncremental(symbolId);
    return symbolId;
  }

  /// Shorthand for identifier-like property names.
  /// For now, we emit them as strings and the printer restores them to
  /// identifiers if it can.
  // TODO(jmesserly): avoid the round tripping through quoted form.
  js_ast.LiteralString _propertyName(String name) => js.string(name, "'");

  /// Unique identifiers indicating the locations to inline the corresponding
  /// information.
  ///
  /// We cannot generate the source map before the script it is for is
  /// generated so we have generate the script including this identifier in the
  /// JS AST, and then replace it once the source map is generated.  Similarly,
  /// metrics include the size of the source map.
  static const String sourceMapLocationID =
      'SourceMap3G5a8h6JVhHfdGuDxZr1EF9GQC8y0e6u';
  static const String metricsLocationID =
      'MetricsJ7xFWBfSv6ZjrW9yLb21GNzisZr3anSf5h';
}

bool _isInlineJSFunction(Statement? body) {
  var block = body;
  if (block is Block) {
    var statements = block.statements;
    if (statements.length != 1) return false;
    body = statements[0];
  }
  if (body is ReturnStatement) {
    var expr = body.expression;
    return expr is StaticInvocation && isInlineJS(expr.target);
  }
  return false;
}

/// Return true if this is one of the methods/properties on all Dart Objects
/// (toString, hashCode, noSuchMethod, runtimeType).
///
/// Operator == is excluded, as it is handled as part of the equality binary
/// operator.
bool _isObjectMember(String name) {
  // We could look these up on Object, but we have hard coded runtime helpers
  // so it's not really providing any benefit.
  switch (name) {
    case 'hashCode':
    case 'toString':
    case 'noSuchMethod':
    case 'runtimeType':
    case '==':
      return true;
  }
  return false;
}

bool _isObjectGetter(String name) =>
    name == 'hashCode' || name == 'runtimeType';

bool _isObjectMethodTearoff(String name) =>
    // "==" isn't in here because there is no syntax to tear it off.
    name == 'toString' || name == 'noSuchMethod';

bool _isObjectMethodCall(String name, Arguments args) {
  if (name == 'toString') {
    return args.positional.isEmpty && args.named.isEmpty && args.types.isEmpty;
  } else if (name == 'noSuchMethod') {
    return args.positional.length == 1 &&
        args.named.isEmpty &&
        args.types.isEmpty;
  }
  return false;
}

class _SwitchLabelState {
  String label;
  js_ast.Identifier variable;

  _SwitchLabelState(this.label, this.variable);
}

/// Whether [expression] is a constant of the form
/// `const pragma('dyn-module:entry-point')`.
///
/// Used to denote the entrypoint method of a dynamic module.
// TODO(sigmund): move to package:kernel.
bool _isEntrypointPragma(Expression expression, CoreTypes coreTypes) {
  if (expression is! ConstantExpression) return false;
  final value = expression.constant;
  if (value is! InstanceConstant) return false;
  if (value.classReference != coreTypes.pragmaClass.reference) return false;
  final name = value.fieldValues[coreTypes.pragmaName.fieldReference];
  if (name is! StringConstant) return false;
  return name.value == 'dyn-module:entry-point';
}
