// 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/js_interop.dart'
    show getDartJSInteropJSName, hasDartJSInteropAnnotation;
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
    show ExtensionIndex;
import 'package:front_end/src/api_prototype/external_effect.dart'
    show ExternalEffect;
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: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,
        libraryUriToImportName,
        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';

/// The groups of compiled invocation arguments ready to be flattened into a
/// single [js_ast.Array] for statically sound calls or into separate packets
/// for runtime checked calls.
typedef _ArgumentGroups = ({
  List<js_ast.Expression>? typeArguments,
  List<js_ast.Expression>? positionalArguments,
  List<js_ast.Property>? namedArguments,
});

/// 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<Variable, 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>,
        StatementVisitorInternalNodeMixin<js_ast.Statement>,
        StatementVisitorExperimentExclusionMixin<js_ast.Statement>,
        ExpressionVisitorInternalNodeMixin<js_ast.Expression>,
        ExpressionVisitorExperimentExclusionMixin<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 every mixin application to a unique identifier.
  ///
  /// A mixin application is represented as a (mixin, class) pair, where
  /// 'mixin' is being mixed into 'class'. Anonymous mixins are already
  /// unique per mixin application and so pass themselves in as both 'mixin'
  /// and 'class'.
  ///
  /// This mapping is used when generating super property getters in mixins.
  final Map<(Class, Class), js_ast.Identifier> _mixinCache = {};

  /// Records a reference to a mixin application's passed in superclass.
  /// (see [_emitMixinStatement]).
  final Map<Class, js_ast.Identifier> _mixinSuperclassCache = {};

  /// 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 = <Variable, js_ast.Identifier>{};

  /// Identifiers for kernel variables with an analogous identifier in JS.
  ///
  /// [Variable.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<Variable, 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
  Variable? _rethrowParameter;

  Set<Class>? _pendingClasses;

  /// Temporary variables mapped to their corresponding JavaScript variable.
  final _tempVariables = <Variable, 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>{};

  /// Imported libraries in incremental mode, and the temporaries used to refer
  /// to them.
  final _incrementalImports = <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;

  // The direct `_as` methods for primitive types.
  final Member _asBool;
  final Member _asDouble;
  final Member _asInt;
  final Member _asNum;
  final Member _asObject;
  final Member _asString;
  final Member _asBoolQ;
  final Member _asDoubleQ;
  final Member _asIntQ;
  final Member _asNumQ;
  final Member _asStringQ;

  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'),
      _asBool = sdk.getTopLevelMember('dart:_rti', '_asBool'),
      _asDouble = sdk.getTopLevelMember('dart:_rti', '_asDouble'),
      _asInt = sdk.getTopLevelMember('dart:_rti', '_asInt'),
      _asNum = sdk.getTopLevelMember('dart:_rti', '_asNum'),
      _asObject = sdk.getTopLevelMember('dart:_rti', '_asObject'),
      _asString = sdk.getTopLevelMember('dart:_rti', '_asString'),
      _asBoolQ = sdk.getTopLevelMember('dart:_rti', '_asBoolQ'),
      _asDoubleQ = sdk.getTopLevelMember('dart:_rti', '_asDoubleQ'),
      _asIntQ = sdk.getTopLevelMember('dart:_rti', '_asIntQ'),
      _asNumQ = sdk.getTopLevelMember('dart:_rti', '_asNumQ'),
      _asStringQ = sdk.getTopLevelMember('dart:_rti', '_asStringQ');

  /// 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.objectNullableRawType];
      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');

    // 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 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;

    return libraryUriToImportName(uri);
  }

  /// 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);
    }
    // Creating a function and setting the library object as the prototype
    // serves as a signal to V8 that the members of the library should get
    // optimized for fast lookup.
    // Do not remove without testing for performance regressions.
    _moduleItems.add(
      js.statement('(function() {}).prototype = #', [
        _libraries[_currentLibrary!],
      ]),
    );
    _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);

    // Store identifiers for a mixin application's passed in superclass.
    // (see [_emitMixinStatement]).
    if (c.isMixinDeclaration && !c.isMixinClass) {
      _mixinSuperclassCache.putIfAbsent(
        c,
        () => _emitScopedId(getLocalClassName(c.superclass!)),
      );
    }

    // 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);
    var jsStaticMethodTypeTags = <js_ast.Statement>[];
    for (var member in c.procedures) {
      // TODO(#57049): We tag all static members because we don't know if
      // they've been changed after a hot reload. This won't be necessary if we
      // can tag them during the delta diff phase.
      if (member.isStatic && _reifyTearoff(member) && !member.isExternal) {
        var result = _emitStaticTarget(member);
        // We only need to tag static functions that are torn off at
        // compile-time. We attach these late so tearoffs have access to
        // their types.
        var reifiedType = member.function.computeThisFunctionType(
          member.enclosingLibrary.nonNullable,
        );
        jsStaticMethodTypeTags.add(
          _emitFunctionTagged(result, reifiedType, asLazy: true).toStatement(),
        );
      }
    }

    _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);
    body.addAll(jsStaticMethodTypeTags);

    // 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 = _mixinSuperclassCache[c]!;
    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);
    }

    // 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(''),
            [?mixinRti],
          ]);
        }

        var name = ctor.name.text;
        var ctorBody = [
          ?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 mixinId = _emitMixinId(m, m.isAnonymousMixin ? m : c);
      // 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;

      // Mixins need to be exposed in this library in case they are
      // referenced in a super getter.
      // TODO(markzipan): We originally bound mixin classes to a temporary as a
      // workaround for a now-resolved Chrome issue. However, a side effect of
      // this operation is that mixin IDs are renamed by the local visitor. We
      // can remove this hoisting after we give mixins unique names.
      var enclosingLibrary = _emitLibraryName(_currentLibrary!);
      var mixinAccessor = js_ast.PropertyAccess(
        enclosingLibrary,
        js.string(mixinId.name),
      );
      body.addAll([
        js.statement('const # = #', [
          mixinId,
          js_ast.ClassExpression(
            _emitScopedId('${mixinId.name}\$'),
            baseClass,
            forwardingMethodStubs,
          ),
        ]),
        js.statement('# = #', [mixinAccessor, mixinId]),
      ]);

      emitMixinConstructors(mixinId, superclass, mixinClass, mixinType);
      hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(mixinClass);
      var mixinTargetLabel = js.string(fullyResolvedMixinClassLabel(m));
      if (shouldDefer(mixinType)) {
        deferredSupertypes.add(
          () => _runtimeStatement('applyMixin(#, #, #)', [
            mixinId,
            emitDeferredClassRef(mixinType),
            mixinTargetLabel,
          ]),
        );
      } else {
        body.add(
          _runtimeStatement('applyMixin(#, #, #)', [
            mixinId,
            emitClassRef(mixinType),
            baseClass,
          ]),
        );
      }

      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 methodsImmediateTarget = <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);

      var memberName = _declareMemberName(member);
      if (!member.isAccessor) {
        var immediateTarget = js.string(fullyResolvedTargetLabel(member));
        methodsImmediateTarget.add(
          js_ast.Property(memberName, immediateTarget),
        );
      }

      if (needsSignature) {
        js_ast.Expression type;
        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);
    emitSignature('MethodsImmediateTarget', methodsImmediateTarget);
    // 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)) {
      result = f.computeThisFunctionType(Nullability.nonNullable);
    } else {
      var fComputed = f.computeThisFunctionType(Nullability.nonNullable);
      var fComputedNamedByName = {
        for (NamedType namedParameter in fComputed.namedParameters)
          namedParameter.name: namedParameter,
      };
      DartType reifyParameter(
        FunctionParameter parameter,
        DartType fComputedParameter,
      ) => isCovariantParameter(parameter)
          ? _coreTypes.objectNullableRawType
          : fComputedParameter;
      NamedType reifyNamedParameter(
        NamedParameter parameter,
        NamedType fComputedNamedParameter,
      ) {
        assert(parameter.parameterName == fComputedNamedParameter.name);
        return NamedType(
          parameter.parameterName,
          reifyParameter(parameter, fComputedNamedParameter.type),
        );
      }

      // TODO(jmesserly): do covariant type parameter bounds also need to be
      // reified as `Object`?
      result = FunctionType(
        DartTypeList.generate(
          f.positionalParameters.length,
          (index) => reifyParameter(
            f.positionalParameters[index],
            fComputed.positionalParameters[index],
          ),
        ),
        f.returnType,
        Nullability.nonNullable,
        namedParameters: NamedDartTypeList.mapped(
          f.namedParameters,
          (p) => reifyNamedParameter(p, fComputedNamedByName[p.parameterName]!),
        )..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(visitVariable(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),
          [?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 = [?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])).toStatement()
          ..sourceInformation = _nodeStart(hoverInfo),
      );
    }

    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(visitVariable(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(Nullability.nonNullable),
    ) as FunctionType;
    var function = member.function;
    var body = <js_ast.Statement>[];
    var typeParameters = function.typeParameters;
    var superTypeParameters = superMethodType.typeParameters;
    var typeFormals = _emitTypeFormals(typeParameters);
    for (var i = 0; i < typeParameters.length; i++) {
      var typeParameter = typeParameters[i];
      var superBound = superTypeParameters[i].bound;
      if (typeParameter.isCovariantByClass && !_types.isTop(superBound)) {
        body.add(
          js.statement('#.checkTypeBound(#, #, #, #)', [
            _emitLibraryName(_rtiLibrary),
            typeFormals[i],
            _emitType(superBound),
            _propertyName(typeParameter.name!),
            js.string(member.name.text),
          ]),
        );
      }
    }
    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.parameterName);
      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.parameterName == param.parameterName,
            ),
          )) {
        var name = _propertyName(param.parameterName);
        var paramType = superMethodType.namedParameters.firstWhere(
          (n) => n.name == param.parameterName,
        );
        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;
    final 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');
    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) {
          // A dummy setter is still required to indicate writeable.
          accessors.add(
            js_ast.Method(
              access,
              js_ast.Fun([_emitIdentifier('value')], js_ast.Block(const [])),
              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) {
    return _emitJSInterop(n) ??
        _emitTopLevelNameNoExternalInterop(n, 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 = false}) {
    var c = m.enclosingClass;
    var actualUseExtension =
        useExtension || (c != null && _extensionTypes.isNativeClass(c));
    return _emitMemberName(
      m.name.text,
      isStatic: m is Field ? m.isStatic : (m as Procedure).isStatic,
      useExtension: actualUseExtension,
      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(ExpressionList(f), types: DartTypeList(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();
    for (var p in procedures) {
      if (!p.isAccessor) {
        _moduleItems.add(_emitLibraryFunction(p));
      }
      // TODO(#57049): We tag all static members because we don't know if
      // they've been changed after a hot reload. This won't be necessary if we
      // can tag them during the delta diff phase.
      if (p.isStatic && _reifyTearoff(p) && !p.isExternal) {
        var nameExpr = _emitTopLevelName(p);
        _moduleItems.add(
          _emitFunctionTagged(
            nameExpr,
            p.function.computeThisFunctionType(p.enclosingLibrary.nonNullable),
            asLazy: true,
          ).toStatement(),
        );
      }
    }
    _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 && _isDynamicModuleEntryPoint(p, _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 asLazy = false,
  }) {
    var typeRep = _emitType(
      // Avoid tagging a closure as Function? or Function*
      type.withDeclaredNullability(Nullability.nonNullable),
    );
    if (type.typeParameters.isEmpty) {
      return asLazy
          ? _runtimeCall('lazyFn(#, () => #)', [fn, typeRep])
          : _runtimeCall('fn(#, #)', [fn, typeRep]);
    } else {
      var typeParameterDefaults = [
        for (var parameter in type.typeParameters)
          _emitType(parameter.defaultType),
      ];
      var defaultInstantiatedBounds = _emitConstList(
        const DynamicType(),
        typeParameterDefaults,
      );
      return asLazy
          ? _runtimeCall('lazyGFn(#, () => #, () => #)', [
              fn,
              typeRep,
              defaultInstantiatedBounds,
            ])
          : _runtimeCall('gFn(#, #, #)', [
              fn,
              typeRep,
              defaultInstantiatedBounds,
            ]);
    }
  }

  /// 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():
          // Cache ground types in the type table for fast lookup. The table
          // will lazily lookup the RTI object on first access and then replace
          // the lazy getter with the initialized RTI object.
          return _typeTable.nameType(
            type,
            js.call('#._Universe.eval(#, "$recipe", true)', [
              _emitLibraryName(_rtiLibrary),
              _runtimeCall('typeUniverse'),
            ]),
          );
        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;
            // By convention we create a binding environment with "dynamic" as
            // the base.
            env = _emitType(const DynamicType());
            // Bind all type arguments to it.
            for (var typeParameter in environmentTypes) {
              env = emitRtiBind(env, typeParameter);
            }
          }
          return emitRtiEval(env, recipe);
        case RtiTypeEnvironment():
          // RTI type environments take the form of a preconstructed RTI that
          // is accessible via a known parameter name.
          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 ExtendedTypeEnvironment():
          // 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();
    _incrementalImports.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()) {
      _emitLibraryName(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(
    Variable 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;
    _nullableInference.enterFunction(fn);
    var result = _withLetScope(action);
    _nullableInference.exitFunction(fn);
    _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;

  /// 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(
      FunctionParameter p,
      js_ast.Identifier jsParam,
      bool isOptional,
    ) {
      // 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) ||
          // TODO(52582): This should be unreachable once the CFE ensures that
          // redirecting factories parameter types match the target constructor.
          // Matches dart2js check semantics for redirecting factory tearoffs.
          // If a non-nullable optional argument with a null initializer is
          // detected, we add an additional covariant check at runtime.
          (f.parent is Procedure &&
              isOptional &&
              isConstructorTearOffLowering(f.parent as Procedure) &&
              !p.type.isPotentiallyNullable &&
              !p.defaultValue!
                  .getStaticType(_staticTypeContext)
                  .isPotentiallyNonNullable)) {
        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));
      }
    }

    var counter = 0;
    for (var p in f.positionalParameters) {
      var jsParam = _emitVariableRef(p);
      if (_checkParameters) {
        initParameter(p, jsParam, counter >= f.requiredParameterCount);
      }
      counter++;
    }
    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.parameterName);
      var defaultValue = _defaultParamValue(p);
      body.add(
        js.statement('let # = # && # ? #.# : #;', [
          jsParam,
          _namedArgumentTemp,
          _namedArgumentProbe(paramName),
          _namedArgumentTemp,
          paramName,
          defaultValue,
        ]),
      );

      if (_checkParameters) {
        initParameter(p, jsParam, !p.isRequired);
      }
    }

    // '_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 _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(Variable 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> typeFormals,
    List<js_ast.Statement> body,
  ) {
    for (var t in typeFormals) {
      var bound = t.bound.extensionTypeErasure;
      if (t.isCovariantByClass && !_types.isTop(bound)) {
        // TODO(nshahan): Ensure we have a name for the method and then
        // just call the `checkTypeBound()` in the rti library directly.
        body.add(
          _runtimeStatement('checkTypeBound(#, #, #)', [
            _emitType(TypeParameterType(t, Nullability.undetermined)),
            _emitType(bound),
            _propertyName(t.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.parameterName,
        for (var p in f.namedParameters) p.parameterName,
      };

      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.boolNonNullableRawType,
      );
      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.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 d) =>
          js_ast.VariableInitialization(
            _emitVariableDef(d.variable),
            _visitInitializer(d.variable.initializer, d.variable.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 initializers 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
  /// initialized 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 stmt in node.variables)
        stmt.variable: _emitVariableDef(stmt.variable),
    };
    var prevVariableTempIds = {
      for (var stmt in node.variables)
        stmt.variable: _emitScopedId('t#_prev_${stmt.variable.cosmeticName!}'),
    };
    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 stmt in node.variables)
        js.statement('# = #;', [
          loopVariableIds[stmt.variable]!,
          _visitInitializer(
            stmt.variable.initializer,
            stmt.variable.annotations,
          ),
        ]),
    ]);
    var prevInits = js_ast.Block([
      // Initialize fresh loop variables with the value from the previous
      // iteration.
      for (var stmt in node.variables)
        js.statement('# = #;', [
          loopVariableIds[stmt.variable],
          prevVariableTempIds[stmt.variable],
        ]),
      // Original update expressions.
      for (var update in node.updates) _visitExpression(update).toStatement(),
    ]);
    return js_ast.Block([
        // Create temporary variables for the initialization flag and previous
        // loop variables.
        js_ast.VariableDeclarationList('let', [
          js_ast.VariableInitialization(
            initFlagTempId,
            js_ast.LiteralBool(true),
          ),
          for (var stmt in node.variables)
            js_ast.VariableInitialization(
              prevVariableTempIds[stmt.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 stmt in node.variables)
                    js_ast.VariableInitialization(
                      loopVariableIds[stmt.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 stmt in node.variables)
                js.statement('# = #;', [
                    prevVariableTempIds[stmt.variable]!,
                    _emitVariableRef(stmt.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(stmt.variable),
            ]),
          )
          // The while loop gets mapped to the original 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.cosmeticName != null &&
          js_ast.variableIsReferenced(node.variable.cosmeticName!, 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.nonNullableRawType(
      _asyncStreamIteratorClass,
    );
    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 = SyntheticVariable(cosmeticName: '#e');
    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) ??
        SyntheticVariable(cosmeticName: '#ex');

    var stackTraceParameter =
        (clauses.length == 1 ? clauses[0].stackTrace : null) ??
        (clauses.any((c) => c.stackTrace != null)
            ? SyntheticVariable(cosmeticName: '#st')
            : 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,
    Variable exceptionParameter,
    Variable? stackTraceParameter,
  ) {
    var body = <js_ast.Statement>[];
    var vars = HashSet<String>();

    void declareVariable(Variable? variable, Variable? value) {
      if (variable == null || value == null) return;
      vars.add(variable.cosmeticName!);
      if (variable.cosmeticName != value.cosmeticName) {
        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 visitVariable(Variable 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(Nullability.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.cosmeticName) {
      id = id.withSourceInformation(
        _variableSpan(node.fileOffset, v.cosmeticName!.length),
      );
    }
    return id;
  }

  /// Detects temporary variables so we can avoid displaying
  /// them in the debugger if needed.
  bool _isTemporaryVariable(Variable 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.cosmeticName == null ||
        v.cosmeticName!.startsWith('#');
  }

  /// Creates a temporary name recognized by the debugger.
  /// Assumes `_isTemporaryVariable(v)`  is true.
  String? _debuggerFriendlyTemporaryVariableName(Variable 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.cosmeticName != null) {
      return 't\$${v.cosmeticName}';
    }
    return null;
  }

  js_ast.ScopedId _emitVariableRef(Variable v) {
    if (_isTemporaryVariable(v)) {
      var name = _debuggerFriendlyTemporaryVariableName(v);
      name ??= 't\$${_tempVariables.length}';
      return _tempVariables.putIfAbsent(
        v,
        () => _emitScopedId(name!, needsCapture: true),
      );
    }
    var name = v.cosmeticName!;
    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(Variable 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 (member.isCoreObjectGetter && _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 (member.isToStringOrNoSuchMethod &&
        _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('tearoff(#, null, #)', [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 _runtimeCall('dput$_replSuffix(#, #, #)', [
      _visitExpression(node.receiver),
      _emitMemberName(node.name.text),
      _visitExpression(node.value),
    ]);
  }

  @override
  js_ast.Expression visitInstanceSet(InstanceSet node) {
    var target = node.interfaceTarget;
    var value = isJsMember(target) ? _assertInterop(node.value) : node.value;
    return js.call('#.# = #', [
      _visitExpression(node.receiver),
      _emitMemberName(node.name.text, member: target),
      _visitExpression(value),
    ]);
  }

  /// 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 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' : '';

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

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

  /// Emits a reference to a distinct mixin application, represented by
  /// a [mixedInClass] being mixed into [baseClass].
  ///
  /// Anonymous mixins should pass themselves as [baseClass] since they are
  /// already uniquely generated per distinct mixin application
  js_ast.Identifier _emitMixinId(Class mixedInClass, Class baseClass) {
    var mixinName = mixedInClass.name;
    if (!mixedInClass.isAnonymousMixin) {
      mixinName += '#${baseClass.name}';
    }
    return _mixinCache.putIfAbsent((
      mixedInClass,
      baseClass,
    ), () => _emitScopedId(mixinName));
  }

  js_ast.Expression _emitSuperPropertyGet(Member target) {
    if (_reifyTearoff(target)) {
      if (_superAllowed) {
        var jsName = _declareMemberName(target);
        var enclosingClass = target.enclosingClass!;
        js_ast.Expression? supertypeReference =
            _mixinSuperclassCache[_currentClass!];
        if (supertypeReference == null) {
          if (enclosingClass.isAnonymousMixin) {
            var mixinId = _emitMixinId(enclosingClass, enclosingClass);
            var enclosingLibrary = _emitLibraryName(getLibrary(enclosingClass));
            supertypeReference = js_ast.PropertyAccess(
              enclosingLibrary,
              js.string(mixinId.name),
            );
          } else {
            supertypeReference = _emitTopLevelNameNoExternalInterop(
              enclosingClass,
            );
          }
        }
        return _runtimeCall('superTearoff(this, #, #)', [
          supertypeReference,
          jsName,
        ]);
      } else {
        return _emitSuperTearoffFromDisallowedContext(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 propertyAccessor = _emitStaticTarget(target);
    var context = propertyAccessor.receiver;
    var property = propertyAccessor.selector;
    var result = js.call('#.#', [context, property]);
    if (_reifyTearoff(target)) {
      var enclosingMemberTargetName = js.string(
        fullyResolvedTargetLabel(target),
      );
      return _runtimeCall('staticTearoff(#, #, #)', [
        context,
        enclosingMemberTargetName,
        property,
      ]);
    }
    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 _emitDynamicInvocation(
      node.receiver,
      node.name.text,
      node.arguments,
    );
  }

  @override
  js_ast.Expression visitFunctionInvocation(FunctionInvocation node) {
    var name = node.name.text;
    assert(name == 'call');
    if (node.functionType == null) {
      // A `null` here implies the receiver is typed as `Function`. There isn't
      // any more type information available at compile time to know this
      // invocation is sound so a dynamic call will handle the checks at
      // runtime.
      return _emitDynamicInvocation(node.receiver, name, node.arguments);
    }
    return js_ast.Call(
      _visitExpression(node.receiver),
      _emitArgumentList(node.arguments),
    );
  }

  @override
  js_ast.Expression visitInstanceInvocation(InstanceInvocation node) {
    var target = node.interfaceTarget;
    if (target.isPrimitiveOperator) {
      return _emitPrimitiveOperatorInvocation(node);
    }
    var receiver = node.receiver;
    var jsReceiver = _visitExpression(receiver);
    var jsArguments = _emitArgumentList(node.arguments, target: target);
    if (node.isNativeListInvariantAddInvocation(_coreTypes.listClass)) {
      return js.call('#.push(#)', [jsReceiver, jsArguments]);
    }
    var name = node.name.text;
    if (name == 'call') {
      var directCallInvocation = _emitDirectInstanceCallInvocation(node);
      if (directCallInvocation != null) {
        return directCallInvocation;
      }
    }
    if (target.isToStringOrNoSuchMethodWithDefaultSignature &&
        _shouldCallObjectMemberHelper(receiver)) {
      // Handle Object methods when the receiver could potentially be `null` or
      // JavaScript interop values with static helper methods.
      // The names of the static helper methods in the runtime must match the
      // names of the Object instance members.
      return _runtimeCall('#(#, #)', [name, jsReceiver, jsArguments]);
    }
    // Otherwise generate this as a normal typed method call.
    var jsName = _emitMemberName(name, member: target);
    var invocation = js.call('#.#(#)', [jsReceiver, jsName, jsArguments]);
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(invocation)
        : invocation;
  }

  /// Returns a direct invocation to support a `call()` method invocation when
  /// the receiver is considered directly callable, otherwise returns
  /// `null`.
  ///
  /// For example if `fn` is statically typed as a function type, then
  /// `fn.call()` would be considered directly callable and compiled as `fn()`.
  js_ast.Expression? _emitDirectInstanceCallInvocation(
    InstanceInvocation node,
  ) {
    // Erasing the extension types here to support existing callable behavior
    // 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 = node.receiver
        .getStaticType(_staticTypeContext)
        .extensionTypeErasure;
    if (!_isDirectCallable(receiverType)) return null;
    // Handle call methods on function types as function calls.
    var invocation = js_ast.Call(
      _visitExpression(node.receiver),
      _emitArgumentList(node.arguments, target: node.interfaceTarget),
    );
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(invocation)
        : invocation;
  }

  /// Returns an invocation of a primitive operator.
  ///
  /// See [ProcedureHelpers.isPrimitiveOperator].
  js_ast.Expression _emitPrimitiveOperatorInvocation(InstanceInvocation node) {
    var receiver = node.receiver;
    var target = node.interfaceTarget;
    var arguments = node.arguments;
    assert(arguments.types.isEmpty && arguments.named.isEmpty);
    // JavaScript interop does not support overloading of these operators.
    return switch (arguments.positional.length) {
      0 => _emitUnaryOperator(receiver, target, node),
      1 => _emitBinaryOperator(receiver, target, arguments.positional[0], node),
      // Should always be a compile time error but here for exhaustiveness.
      _ => throw UnsupportedError(
        'Invalid number of positional arguments.\n'
        'Found: ${arguments.positional.length}\n'
        'Operator: ${node.name.text} '
        '${node.location}',
      ),
    };
  }

  @override
  js_ast.Expression visitInstanceGetterInvocation(
    InstanceGetterInvocation node,
  ) {
    if (node.functionType == null) {
      // A `null` here implies the receiver must be typed as `dynamic` or
      // `Function`. There isn't any more type information available at compile
      // time to know this invocation is sound so a dynamic call will handle the
      // checks at runtime.
      return _emitDynamicInvocation(
        node.receiver,
        node.name.text,
        node.arguments,
      );
    }
    var getterInvocation = _emitInstanceGetterInvocation(node);
    return _isNullCheckableJsInterop(node.interfaceTarget)
        ? _wrapWithJsInteropNullCheck(getterInvocation)
        : getterInvocation;
  }

  js_ast.Expression _emitInstanceGetterInvocation(
    InstanceGetterInvocation node,
  ) {
    var receiver = _visitExpression(node.receiver);
    var arguments = _emitArgumentList(
      node.arguments,
      target: node.interfaceTarget,
    );
    if (node.name.text == 'call') {
      // Erasing the extension types here to support existing callable behavior
      // 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 = node.receiver
          .getStaticType(_staticTypeContext)
          .extensionTypeErasure;
      if (_isDirectCallable(receiverType)) {
        // Call methods on function types should be handled as function calls.
        return js_ast.Call(receiver, arguments);
      }
    }
    var memberName = _emitMemberName(
      node.name.text,
      member: node.interfaceTarget,
    );
    // We must erase the extension type to potentially 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 because:
    //  - Extension types that do not implement 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 erasedGetterType = node.interfaceTarget.getterType.extensionTypeErasure;
    if (erasedGetterType is TypeParameterType) {
      // Instantiate with the static type so there is a concrete interface to
      // inspect for the callable target check.
      var receiverClass = node.interfaceTarget.enclosingClass!;
      var instantiatedClassType = node.receiver.getStaticTypeAsInstanceOf(
        receiverClass,
        _staticTypeContext,
      );
      var instantiatedGetterType = Substitution.fromInterfaceType(
        instantiatedClassType,
      ).substituteType(erasedGetterType);
      erasedGetterType = instantiatedGetterType.extensionTypeErasure;
    }
    if (erasedGetterType is InterfaceType) {
      var callName = _implicitCallTarget(erasedGetterType);
      if (callName != null) {
        return js.call('#.#.#(#)', [receiver, memberName, callName, arguments]);
      }
    }
    return js.call('#.#(#)', [receiver, memberName, arguments]);
  }

  @override
  js_ast.Expression visitLocalFunctionInvocation(LocalFunctionInvocation node) {
    assert(node.name.text == 'call');
    final localName = VariableGet(node.variable)..fileOffset = node.fileOffset;
    return js_ast.Call(
      _visitExpression(localName),
      _emitArgumentList(node.arguments),
    );
  }

  @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);
  }

  /// Returns an invocation of the runtime helpers `dcall`, `dgcall`, `dsend`,
  /// or `dgsend` to perform dynamic checks before invoking [memberName] on
  /// [receiver] and passing [arguments].
  js_ast.Expression _emitDynamicInvocation(
    Expression receiver,
    String memberName,
    Arguments arguments,
  ) {
    var jsArgs = [_visitExpression(receiver)];
    String jsCode;
    var (:typeArguments, :positionalArguments, :namedArguments) =
        _emitArgumentGroups(arguments, isJSInterop: false);
    if (memberName == 'call') {
      if (typeArguments != null) {
        jsCode = 'dgcall(#, #';
        jsArgs.add(js_ast.ArrayInitializer(typeArguments));
      } else {
        jsCode = 'dcall(#';
      }
    } else {
      if (typeArguments != null) {
        jsCode = 'dgsend$_replSuffix(#, #, #';
        jsArgs.add(js_ast.ArrayInitializer(typeArguments));
      } else {
        jsCode = 'dsend$_replSuffix(#, #';
      }
      jsArgs.add(_emitMemberName(memberName));
    }
    if (positionalArguments != null) {
      jsCode += ', #';
      jsArgs.add(js_ast.ArrayInitializer(positionalArguments));
    } else {
      jsCode += ', []';
    }
    if (namedArguments != null) {
      jsCode += ', #';
      jsArgs.add(js_ast.ObjectInitializer(namedArguments));
    }
    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;
  }

  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 = _declareMemberName(member);
    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
    // [_emitSuperTearoffFromDisallowedContext].
    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.parameterName),
          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 special string used for identifying a torn off member [m].
  ///
  /// This tag is used for determining tearoff equality. We attach these tags
  /// at tearoff time for static tearoffs and in the method signature for
  /// dynamic tearoffs.
  String fullyResolvedTargetLabel(Member m) {
    return '${m.enclosingLibrary.importUri}:${m.enclosingClass?.name ?? ""}';
  }

  /// Generates a special string used for identifying class [c]'s applied mixed
  /// in members.
  ///
  /// This tag is used for determining tearoff equality. We attach these tags
  /// at tearoff time for static tearoffs and in the method signature for
  /// dynamic tearoffs.
  String fullyResolvedMixinClassLabel(Class c) {
    return '${c.enclosingLibrary.importUri}:${c.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 _emitSuperTearoffFromDisallowedContext(Member member) {
    var jsName = _declareMemberName(member);
    var name = '_#super#tearOff#${member.name.text}';
    var jsMethod = _superHelpers.putIfAbsent(name, () {
      var superclass = member.enclosingClass!;
      var supertypeReference =
          _mixinSuperclassCache[superclass] ??
          _emitTopLevelNameNoExternalInterop(superclass);
      var jsReturnValue = _runtimeCall('superTearoff(this, #, #)', [
        supertypeReference,
        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 (ExternalEffect.isExternalEffect(node)) {
      return js_ast.LiteralNull();
    }
    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 Variable:
                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 (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),
            '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.isEmpty) {
        if (name == 'hotRestartGeneration') {
          return _runtimeCall('hotRestartIteration');
        }
      }
      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);
      var namedProperties = <String, Expression>{};
      for (var named in node.arguments.named) {
        var name = named.name;
        for (var parameter in target.function.namedParameters) {
          if (parameter.parameterName == named.name) {
            var customName = getDartJSInteropJSName(parameter);
            if (customName.isNotEmpty) {
              name = customName;
            }
            break;
          }
        }
        namedProperties[name] = named.value;
      }
      return _emitObjectLiteral(namedProperties, isDartJsInterop: true);
    }
    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 (_callMethodUncheckedRegex.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 (_callConstructorUncheckedRegex.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.PropertyAccess _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 annotationName = _annotationName(target, isJSName);
          var memberName = annotationName == null
              ? _emitStaticMemberName(target.name.text, target)
              : js.string(annotationName);
          return js_ast.PropertyAccess(
            _runtimeCall('global.#', [nativeName[0]]),
            memberName,
          );
        }
      }
      return js_ast.PropertyAccess(
        _emitStaticClassName(c, isExternal),
        _emitStaticMemberName(target.name.text, target),
      );
    }
    return _emitTopLevelName(target);
  }

  /// Returns all parts of [node] flattened into a list so they can be passed in
  /// the calling convention for calls with no runtime checks.
  ///
  /// When [types] is `false` any type arguments present in [node] will be
  /// omitted.
  ///
  /// Passing [target] when applicable allows for detection of an annotation to
  /// omit passing type parameters and to detect if positional arguments should
  /// be packaged to be passed to a JavaScript using an interop call.
  List<js_ast.Expression> _emitArgumentList(
    Arguments node, {
    bool types = true,
    Member? target,
  }) {
    types = types && _reifyGenericFunction(target);
    var (
      :typeArguments,
      :positionalArguments,
      :namedArguments,
    ) = _emitArgumentGroups(
      node,
      isJSInterop: target != null && isJsMember(target),
    );
    return [
      if (types && typeArguments != null) ...typeArguments,
      ...?positionalArguments,
      if (namedArguments != null) js_ast.ObjectInitializer([...namedArguments]),
    ];
  }

  /// Returns all arguments from [node] but kept in separate packets so they can
  /// be further processed.
  ///
  /// Facilitates passing arguments in the calling convention used by runtime
  /// helpers that check arguments.
  ///
  /// When [isJSInterop] is `true` the positional arguments are packaged to
  /// be passed to JavaScript via an interop call.
  _ArgumentGroups _emitArgumentGroups(
    Arguments node, {
    required bool isJSInterop,
  }) {
    var typeArguments = node.types.isEmpty
        ? null
        : [for (var typeArgument in node.types) _emitType(typeArgument)];
    var positionalArguments = node.positional.isEmpty
        ? null
        : [
            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),
          ];
    // Named arguments with JS interop are only allowed in object literal
    // constructors. Invocations to those are always transformed by
    // `_emitObjectLiteral` and therefore we should never expect to see a JS
    // interop invocation with named arguments here.
    if (node.named.isNotEmpty) assert(!isJSInterop);
    var namedArguments = node.named.isEmpty
        ? null
        : [for (var arg in node.named) _emitNamedExpression(arg)];

    return (
      typeArguments: typeArguments,
      positionalArguments: positionalArguments,
      namedArguments: namedArguments,
    );
  }

  js_ast.Property _emitNamedExpression(NamedExpression arg) =>
      js_ast.Property(_propertyName(arg.name), _visitExpression(arg.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)) {
      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) => _nullableInference.isNullable(expr);

  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)) {
      var namedProperties = {
        for (final named in node.arguments.named) named.name: named.value,
      };
      return _emitObjectLiteral(
        namedProperties,
        isDartJsInterop: hasDartJSInteropAnnotation(ctorClass),
      );
    }
    // 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), [
      ?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), [
      ?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)) {
      var namedProperties = {
        for (final named in args.named) named.name: named.value,
      };
      return _emitObjectLiteral(
        namedProperties,
        isDartJsInterop: hasDartJSInteropAnnotation(ctorClass),
      );
    }
    // 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);
  }

  /// Given a mapping [namedProperties] between names and their associated
  /// expressions, returns an object literal with the same names mapped to the
  /// transformed expressions.
  ///
  /// This is used for object literal constructors in JS interop.
  ///
  /// If [isDartJsInterop] is true, it implies that this is an object literal
  /// constructor using `dart:js_interop`. If false, this method wraps the
  /// expressions with an [_assertInterop] call.
  js_ast.Expression _emitObjectLiteral(
    Map<String, Expression> namedProperties, {
    required bool isDartJsInterop,
  }) {
    if (namedProperties.isEmpty) return js.call('{}');
    var properties = <js_ast.Property>[];
    for (var name in namedProperties.keys) {
      // `assertInterop` is not needed for `dart:js_interop`. It statically
      // disallows `Function`s from being passed unless they were explicitly
      // passed as an opaque reference, in which case, we shouldn't require the
      // user to wrap them anyways.
      var value = isDartJsInterop
          ? namedProperties[name]!
          : _assertInterop(namedProperties[name]!);
      properties.add(
        js_ast.Property(_propertyName(name), _visitExpression(value)),
      );
    }
    return js_ast.ObjectInitializer([...properties]);
  }

  @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 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;
    return _emitCast(
      jsFrom,
      node.type,
      fromStaticType: fromExpr.getStaticType(_staticTypeContext),
      isTypeError: node.isTypeError,
    );
  }

  js_ast.Expression _emitCast(
    js_ast.Expression value,
    DartType toType, {
    DartType? fromStaticType,
    bool isTypeError = false,
  }) {
    toType = toType.extensionTypeErasure;
    if (_types.isTop(toType)) return value;
    if (fromStaticType != null) {
      fromStaticType = fromStaticType.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);
      //      }
      //
      if (!isTypeError && _types.isSubtypeOf(fromStaticType, toType)) {
        return value;
      }
      if (!isTypeError &&
          _mustBeNonNullable(toType) &&
          DartTypeEquivalence(
            _coreTypes,
            ignoreTopLevelNullability: true,
          ).areEqual(fromStaticType, toType)) {
        // If the underlying type is the same, we only need a null check.
        return _runtimeCall('nullCast(#, #)', [value, _emitType(toType)]);
      }
      // All Dart number types map to a JavaScript Number. We can specialize
      // these cases.
      if (_typeRep.isNumber(fromStaticType) && _typeRep.isNumber(toType)) {
        // If `toType` is some form of `num`, it should have been filtered
        // above.
        if (toType == _coreTypes.doubleNullableRawType) {
          // Any number/nullability -> double? : no-op
          return value;
        }
        if (toType == _coreTypes.doubleNonNullableRawType) {
          if (fromStaticType.nullability == Nullability.nonNullable) {
            // Any non-nullable number -> double : no-op
            return value;
          }
          // Any number/nullability -> double : null check
          return _runtimeCall('nullCast(#, #)', [value, _emitType(toType)]);
        }
      }
    }
    var directMethod = _directCastMethod(toType);
    if (directMethod != null) {
      return js.call('#(#)', [_emitTopLevelName(directMethod), value]);
    }
    return js.call('#.#(#)', [
      _emitType(toType),
      _emitMemberName(js_ast.FixedNames.rtiAsField, memberClass: _rtiClass),
      value,
    ]);
  }

  /// Returns the direct `_as` method when [type] is a primitive type otherwise,
  /// `null`.
  Member? _directCastMethod(DartType type) {
    if (type is InterfaceType && type.typeArguments.isEmpty) {
      if (type.nullability == Nullability.nonNullable) {
        if (type == _types.coreTypes.boolNonNullableRawType) return _asBool;
        if (type == _types.coreTypes.doubleNonNullableRawType) return _asDouble;
        if (type == _types.coreTypes.intNonNullableRawType) return _asInt;
        if (type == _types.coreTypes.numNonNullableRawType) return _asNum;
        if (type == _types.coreTypes.objectNonNullableRawType) return _asObject;
        if (type == _types.coreTypes.stringNonNullableRawType) return _asString;
      } else if (type.nullability == Nullability.nullable) {
        if (type == _types.coreTypes.boolNullableRawType) return _asBoolQ;
        if (type == _types.coreTypes.doubleNullableRawType) return _asDoubleQ;
        if (type == _types.coreTypes.intNullableRawType) return _asIntQ;
        if (type == _types.coreTypes.numNullableRawType) return _asNumQ;
        if (type == _types.coreTypes.stringNullableRawType) return _asStringQ;
      }
    }
    return null;
  }

  @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,
      DartTypeList(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,
        DartTypeList(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(node.value);
    var body = _visitExpression(node.body);
    var temp = _tempVariables.remove(v);
    // TODO(eernst): Remove the following `if` if anonymous-methods is rejected.
    // Otherwise, revise this method to be more readable.
    // See https://github.com/dart-lang/language/issues/260.
    if (temp == null && !_isTemporaryVariable(v)) {
      temp = _emitVariableRef(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.
      return _emitTypeLiteral(node.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, library: node.libraryReference?.asLibrary);

  @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);
    }

    var type = node.getType(_staticTypeContext);
    assert(
      type.nullability == Nullability.nonNullable,
      'An instance constant should only ever have a non-nullable type.',
    );
    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',
      '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).',
      ),
      if (const bool.fromEnvironment('dart.library.io'))
        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.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),
        libraryUriToJsIdentifier(library.importUri),
      );
    }
  }

  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] by default, so the Symbol is scoped properly. Symbol
  /// constants should pass the symbol's [library] if the referenced symbol was
  /// declared outside the current library.
  js_ast.Expression _emitDartSymbol(String symbolName, {Library? library}) {
    // 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(library ?? _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(libraryUriToJsIdentifier(library.importUri));

      _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;

    var activeImports = _incrementalMode ? _incrementalImports : _imports;
    // It's either one of the libraries in this module, or it's an import.
    return _libraries[library] ??
        activeImports.putIfAbsent(
          library,
          () => _isDartLibrary(library, '_rti')
              ? _rtiLibraryId
              : js_ast.ScopedId(libraryUriToJsIdentifier(library.importUri)),
        );
  }

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

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

    if (_incrementalMode && coreModuleName != null) {
      if (_incrementalModules.containsKey(coreModuleName)) {
        modules.putIfAbsent(coreModuleName, () => []);
      }
    }

    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(
                libraryUriToJsIdentifier(library.importUri),
              )) {
            var alias = _jsLibraryAlias(library);
            if (alias != null) {
              var aliasId = js_ast.ScopedId(alias);
              imports.add(
                js_ast.NameSpecifier(aliasId, asName: activeImports[library]),
              );
            } else {
              imports.add(js_ast.NameSpecifier(activeImports[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(
          libraryUriToJsIdentifier(library.importUri),
        )) {
          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';

  /// Matches against the `dart:js_util` `_callMethodUnchecked` and
  /// `_callMethodUncheckedTrustType` variants with 0 to 4 arguments.
  static final RegExp _callMethodUncheckedRegex = RegExp(
    r'^\_callMethodUnchecked(TrustType)?[0-4]',
  );

  /// Matches against the `dart:js_util` `_callConstructorUnchecked` and
  /// `_callConstructorUncheckedTrustType` variants with 0 to 4 arguments.
  static final RegExp _callConstructorUncheckedRegex = RegExp(
    r'^\_callConstructorUnchecked[0-4]',
  );
}

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;
}

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 _isDynamicModuleEntryPoint(Procedure p, CoreTypes coreTypes) {
  return hasPragma(p, 'dyn-module:entry-point', coreTypes);
}
