// Copyright (c) 2015, 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' show HashMap, HashSet;
import 'dart:math' show min, max;

import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/constant.dart'
    show DartObject, DartObjectImpl;
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart'
    show TypeProvider, NamespaceBuilder;
import 'package:analyzer/src/generated/type_system.dart'
    show StrongTypeSystemImpl;
import 'package:analyzer/src/summary/idl.dart' show UnlinkedUnit;
import 'package:analyzer/src/summary/link.dart' as summary_link;
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summarize_ast.dart'
    show serializeAstUnlinked;
import 'package:analyzer/src/summary/summarize_elements.dart'
    show PackageBundleAssembler;
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/task/strong/ast_properties.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart' show SourceLocation;

import '../compiler/js_metalet.dart' as JS;
import '../compiler/js_names.dart' as JS;
import '../compiler/js_utils.dart' as JS;
import '../compiler/module_builder.dart' show pathToJSIdentifier;
import '../compiler/shared_compiler.dart';
import '../js_ast/js_ast.dart' as JS;
import '../js_ast/js_ast.dart' show js;
import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
import 'ast_builder.dart';
import 'element_helpers.dart';
import 'error_helpers.dart';
import 'extension_types.dart' show ExtensionTypeSet;
import 'js_interop.dart';
import 'js_typerep.dart';
import 'module_compiler.dart' show CompilerOptions, JSModuleFile;
import 'nullable_type_inference.dart' show NullableTypeInference;
import 'property_model.dart';
import 'reify_coercions.dart' show CoercionReifier;
import 'side_effect_analysis.dart'
    show ConstFieldVisitor, isStateless, isPotentiallyMutated;
import 'type_utilities.dart';

/// The code generator for Dart Dev Compiler.
///
/// Takes as input resolved Dart ASTs for every compilation unit in every
/// library in the module. Produces a single JavaScript AST for the module as
// output, along with its source map.
///
/// This class attempts to preserve identifier names and structure of the input
/// Dart code, whenever this is possible to do in the generated code.
///
// TODO(jmesserly): we should use separate visitors for statements and
// expressions. Declarations are handled directly, and many minor component
// AST nodes aren't visited, so the visitor pattern isn't helping except for
// expressions (which result in JS.Expression) and statements
// (which result in (JS.Statement).
class CodeGenerator extends Object
    with NullableTypeInference, SharedCompiler<LibraryElement>
    implements AstVisitor<JS.Node> {
  final AnalysisContext context;
  final SummaryDataStore summaryData;

  final CompilerOptions options;
  final StrongTypeSystemImpl rules;

  /// Errors that were produced during compilation, if any.
  final List<AnalysisError> errors;

  JSTypeRep jsTypeRep;

  /// The set of libraries we are currently compiling, and the temporaries used
  /// to refer to them.
  ///
  /// We sometimes special case codegen for a single library, as it simplifies
  /// name scoping requirements.
  final _libraries = Map<LibraryElement, JS.Identifier>();

  /// Imported libraries, and the temporaries used to refer to them.
  final _imports = Map<LibraryElement, JS.TemporaryId>();

  /// The list of dart:_runtime SDK functions; these are assumed by other code
  /// in the SDK to be generated before anything else.
  final _internalSdkFunctions = <JS.ModuleItem>[];

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

  /// The global extension type table.
  final ExtensionTypeSet _extensionTypes;

  /// The variable for the target of the current `..` cascade expression.
  ///
  /// Usually a [SimpleIdentifier], but it can also be other expressions
  /// that are safe to evaluate multiple times, such as `this`.
  Expression _cascadeTarget;

  /// The variable for the current catch clause
  SimpleIdentifier _catchParameter;

  /// In an async* function, this represents the stream controller parameter.
  JS.TemporaryId _asyncStarController;

  final _initializingFormalTemps = HashMap<ParameterElement, JS.TemporaryId>();

  JS.Identifier _extensionSymbolsModule;
  final _extensionSymbols = Map<String, JS.TemporaryId>();

  /// The  type provider from the current Analysis [context].
  final TypeProvider types;

  final LibraryElement coreLibrary;
  final LibraryElement dartJSLibrary;

  /// The dart:async `StreamIterator<T>` type.
  final InterfaceType _asyncStreamIterator;

  /// The dart:core `identical` element.
  final FunctionElement _coreIdentical;

  /// Classes and types defined in the SDK.
  final ClassElement _jsArray;
  final ClassElement boolClass;
  final ClassElement intClass;
  final ClassElement doubleClass;
  final ClassElement interceptorClass;
  final ClassElement nullClass;
  final ClassElement numClass;
  final ClassElement objectClass;
  final ClassElement stringClass;
  final ClassElement functionClass;
  final ClassElement privateSymbolClass;
  final InterfaceType linkedHashMapImplType;
  final InterfaceType identityHashMapImplType;
  final InterfaceType linkedHashSetImplType;
  final InterfaceType identityHashSetImplType;
  final InterfaceType syncIterableType;
  final InterfaceType asyncStarImplType;

  ConstFieldVisitor _constants;

  /// The current function body being compiled.
  FunctionBody _currentFunction;

  Map<TypeDefiningElement, AstNode> _declarationNodes;

  /// The class that's currently emitting top-level (module-level) JS code.
  ///
  /// This is primarily used to forward declare classes so they are available
  /// to JS class `extends`.
  ///
  /// This is not set when inside method bodies, because they are run after we
  /// load modules, so they can freely access all classes.
  TypeDefiningElement _topLevelClass;

  /// The current element being loaded.
  /// We can use this to determine if we're loading top-level code or not:
  ///
  ///     _currentElement == _topLevelClass
  ///
  /// This is also used to find the current compilation unit for emitting source
  /// mappings.
  Element _currentElement;

  final _deferredProperties = HashMap<PropertyAccessorElement, JS.Method>();

  String _libraryRoot;

  bool _superAllowed = true;

  final _superHelpers = Map<String, JS.Method>();

  List<TypeParameterType> _typeParamInConst;

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

  /// 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 _usedCovariantPrivateMembers = HashSet<ExecutableElement>();

  CodeGenerator(AnalysisContext c, this.summaryData, this.options,
      this._extensionTypes, this.errors)
      : context = c,
        rules = StrongTypeSystemImpl(c.typeProvider),
        types = c.typeProvider,
        _asyncStreamIterator = getClass(c, 'dart:async', 'StreamIterator').type,
        _coreIdentical = _getLibrary(c, 'dart:core')
            .publicNamespace
            .get('identical') as FunctionElement,
        _jsArray = getClass(c, 'dart:_interceptors', 'JSArray'),
        interceptorClass = getClass(c, 'dart:_interceptors', 'Interceptor'),
        coreLibrary = _getLibrary(c, 'dart:core'),
        boolClass = getClass(c, 'dart:core', 'bool'),
        intClass = getClass(c, 'dart:core', 'int'),
        doubleClass = getClass(c, 'dart:core', 'double'),
        numClass = getClass(c, 'dart:core', 'num'),
        nullClass = getClass(c, 'dart:core', 'Null'),
        objectClass = getClass(c, 'dart:core', 'Object'),
        stringClass = getClass(c, 'dart:core', 'String'),
        functionClass = getClass(c, 'dart:core', 'Function'),
        privateSymbolClass = getClass(c, 'dart:_js_helper', 'PrivateSymbol'),
        linkedHashMapImplType =
            getClass(c, 'dart:_js_helper', 'LinkedMap').type,
        identityHashMapImplType =
            getClass(c, 'dart:_js_helper', 'IdentityMap').type,
        linkedHashSetImplType = getClass(c, 'dart:collection', '_HashSet').type,
        identityHashSetImplType =
            getClass(c, 'dart:collection', '_IdentityHashSet').type,
        syncIterableType = getClass(c, 'dart:_js_helper', 'SyncIterable').type,
        asyncStarImplType = getClass(c, 'dart:async', '_AsyncStarImpl').type,
        dartJSLibrary = _getLibrary(c, 'dart:js') {
    jsTypeRep = JSTypeRep(rules, c);
  }

  LibraryElement get currentLibrary => _currentElement.library;

  Uri get currentLibraryUri => _currentElement.librarySource.uri;

  CompilationUnitElement get _currentCompilationUnit {
    for (var e = _currentElement;; e = e.enclosingElement) {
      if (e is CompilationUnitElement) return e;
    }
  }

  /// The main entry point to JavaScript code generation.
  ///
  /// Takes the metadata for the build unit, as well as resolved trees and
  /// errors, and computes the output module code and optionally the source map.
  JSModuleFile compile(List<CompilationUnit> compilationUnits) {
    _libraryRoot = options.libraryRoot;
    if (!_libraryRoot.endsWith(path.separator)) {
      _libraryRoot += path.separator;
    }

    var name = options.moduleName;
    invalidModule() =>
        JSModuleFile.invalid(name, formatErrors(context, errors), options);

    if (!options.unsafeForceCompile && errors.any(_isFatalError)) {
      return invalidModule();
    }

    try {
      var module = _emitModule(compilationUnits, name);
      if (!options.unsafeForceCompile && errors.any(_isFatalError)) {
        return invalidModule();
      }

      var dartApiSummary = _summarizeModule(compilationUnits);
      return JSModuleFile(
          name, formatErrors(context, errors), options, module, dartApiSummary);
    } catch (e) {
      if (errors.any(_isFatalError)) {
        // Force compilation failed.  Suppress the exception and report
        // the static errors instead.
        assert(options.unsafeForceCompile);
        return invalidModule();
      }
      rethrow;
    }
  }

  bool _isFatalError(AnalysisError e) {
    if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false;

    // These errors are not fatal in the REPL compile mode as we
    // allow access to private members across library boundaries
    // and those accesses will show up as undefined members unless
    // additional analyzer changes are made to support them.
    // TODO(jacobr): consider checking that the identifier name
    // referenced by the error is private.
    return !options.replCompile ||
        (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
            e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
            e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
  }

  List<int> _summarizeModule(List<CompilationUnit> units) {
    if (!options.summarizeApi) return null;

    if (!units.any((u) => u.declaredElement.source.isInSystemLibrary)) {
      var sdk = context.sourceFactory.dartSdk;
      summaryData.addBundle(
          null,
          sdk is SummaryBasedDartSdk
              ? sdk.bundle
              : (sdk as FolderBasedDartSdk).getSummarySdkBundle());
    }

    var assembler = PackageBundleAssembler();

    var uriToUnit = Map<String, UnlinkedUnit>.fromIterables(
        units.map((u) => u.declaredElement.source.uri.toString()),
        units.map((unit) {
      var unlinked = serializeAstUnlinked(unit);
      assembler.addUnlinkedUnit(unit.declaredElement.source, unlinked);
      return unlinked;
    }));

    summary_link
        .link(
            uriToUnit.keys.toSet(),
            (uri) => summaryData.linkedMap[uri],
            (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
            context.declaredVariables.get)
        .forEach(assembler.addLinkedLibrary);

    var bundle = assembler.assemble();
    // Preserve only API-level information in the summary.
    bundle.flushInformative();
    return bundle.toBuffer();
  }

  JS.Program _emitModule(List<CompilationUnit> compilationUnits, String name) {
    if (moduleItems.isNotEmpty) {
      throw StateError('Can only call emitModule once.');
    }

    for (var unit in compilationUnits) {
      _usedCovariantPrivateMembers.addAll(getCovariantPrivateMembers(unit));
    }

    // Transform the AST to make coercions explicit.
    compilationUnits = CoercionReifier.reify(compilationUnits);
    var items = <JS.ModuleItem>[];
    var root = JS.Identifier('_root');
    items.add(js.statement('const # = Object.create(null)', [root]));

    var isBuildingSdk = compilationUnits
        .any((u) => isSdkInternalRuntime(u.declaredElement.library));
    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.Identifier('dart');
      _extensionSymbolsModule = JS.Identifier('dartx');
    } else {
      // Otherwise allow these to be renamed so users can write them.
      runtimeModule = JS.TemporaryId('dart');
      _extensionSymbolsModule = JS.TemporaryId('dartx');
    }
    _typeTable = TypeTable(runtimeModule);

    // Initialize our library variables.
    var exports = <JS.NameSpecifier>[];
    void emitLibrary(JS.Identifier id) {
      items.add(js.statement('const # = Object.create(#)', [id, root]));
      exports.add(JS.NameSpecifier(id));
    }

    for (var unit in compilationUnits) {
      var library = unit.declaredElement.library;
      if (unit.declaredElement != library.definingCompilationUnit) continue;

      var libraryTemp = isSdkInternalRuntime(library)
          ? runtimeModule
          : JS.TemporaryId(jsLibraryName(_libraryRoot, library));
      _libraries[library] = libraryTemp;
      emitLibrary(libraryTemp);
    }

    // dart:_runtime has a magic module that holds extension method symbols.
    // TODO(jmesserly): find a cleaner design for this.
    if (isBuildingSdk) emitLibrary(_extensionSymbolsModule);

    items.add(JS.ExportDeclaration(JS.ExportClause(exports)));

    // Collect all class/type Element -> Node mappings
    // in case we need to forward declare any classes.
    _declarationNodes = HashMap<TypeDefiningElement, AstNode>.identity();
    for (var unit in compilationUnits) {
      for (var declaration in unit.declarations) {
        var element = declaration.declaredElement;
        if (element is TypeDefiningElement) {
          _declarationNodes[element] = declaration;
        }
      }
    }
    if (compilationUnits.isNotEmpty) {
      _constants = ConstFieldVisitor(context,
          dummySource: resolutionMap
              .elementDeclaredByCompilationUnit(compilationUnits.first)
              .source);
    }

    // Add implicit dart:core dependency so it is first.
    emitLibraryName(coreLibrary);

    // Visit each compilation unit and emit its code.
    //
    // NOTE: declarations 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.
    compilationUnits.forEach(visitCompilationUnit);
    assert(_deferredProperties.isEmpty);

    // Visit directives (for exports)
    compilationUnits.forEach(_emitExportDirectives);

    // Declare imports
    _finishImports(items);
    // Initialize extension symbols
    _extensionSymbols.forEach((name, id) {
      JS.Expression value =
          JS.PropertyAccess(_extensionSymbolsModule, _propertyName(name));
      if (isBuildingSdk) {
        value = js.call('# = Symbol(#)', [value, js.string("dartx.$name")]);
      }
      items.add(js.statement('const # = #;', [id, value]));
    });

    _emitDebuggerExtensionInfo(name);

    // Discharge the type table cache variables and
    // hoisted definitions.
    items.addAll(_typeTable.discharge());
    items.addAll(_internalSdkFunctions);

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

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

  void _emitDebuggerExtensionInfo(String name) {
    var properties = <JS.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.
      properties.add(JS.Property(
          js.escapedString(jsLibraryDebuggerName(_libraryRoot, library)),
          value));
    });

    // Track the module name for each library in the module.
    // This data is only required for debugging.
    moduleItems.add(js
        .statement('#.trackLibraries(#, #, ${JSModuleFile.sourceMapHoleID});', [
      runtimeModule,
      js.string(name),
      JS.ObjectInitializer(properties, multiline: true)
    ]));
  }

  /// If [e] is a property accessor element, this returns the
  /// (possibly synthetic) field that corresponds to it, otherwise returns [e].
  Element _getNonAccessorElement(Element e) =>
      e is PropertyAccessorElement ? e.variable : e;

  /// Returns the name of [e] but removes trailing `=` from setter names.
  // TODO(jmesserly): it would be nice if Analyzer had something like this.
  // `Element.displayName` is close, but it also normalizes operator names in
  // a way we don't want.
  String _getElementName(Element e) => _getNonAccessorElement(e).name;

  bool _isExternal(Element e) =>
      e is ExecutableElement && e.isExternal ||
      e is PropertyInducingElement &&
          ((e.getter?.isExternal ?? false) || (e.setter?.isExternal ?? false));

  /// Returns true iff this element is a JS interop member.
  ///
  /// The element's library must have `@JS(...)` annotation from `package:js`.
  ///
  /// If the element is a class, it must also be marked with `@JS`. Other
  /// elements, such as class members and top-level functions/accessors, should
  /// be marked `external`.
  //
  // TODO(jmesserly): if the element is a member, shouldn't we check that the
  // class is a JS interop class?
  bool _usesJSInterop(Element e) =>
      e?.library != null &&
      _hasJSInteropAnnotation(e.library) &&
      (_isExternal(e) || e is ClassElement && _hasJSInteropAnnotation(e));

  String _getJSNameWithoutGlobal(Element e) {
    if (!_usesJSInterop(e)) return null;
    var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation);
    var jsName =
        getAnnotationName(e, isPublicJSAnnotation) ?? _getElementName(e);
    return libraryJSName != null ? '$libraryJSName.$jsName' : jsName;
  }

  JS.PropertyAccess _emitJSInterop(Element e) {
    var jsName = _getJSNameWithoutGlobal(e);
    if (jsName == null) return null;
    return _emitJSInteropForGlobal(jsName);
  }

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

  JS.Expression _emitJSInteropStaticMemberName(Element e) {
    if (!_usesJSInterop(e)) return null;
    var name = getAnnotationName(e, isPublicJSAnnotation);
    if (name != null) {
      if (name.contains('.')) {
        throw UnsupportedError(
            'static members do not support "." in their names. '
            'See https://github.com/dart-lang/sdk/issues/27926');
      }
    } else {
      name = _getElementName(e);
    }
    return js.escapedString(name, "'");
  }

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

  String _libraryToModule(LibraryElement library) {
    assert(!_libraries.containsKey(library));
    var source = library.source;
    // TODO(jmesserly): we need to split out HTML.
    if (source.uri.scheme == 'dart') {
      return JS.dartSdkModule;
    }
    var summaryPath = (source as InSummarySource).summaryPath;
    var moduleName = options.summaryModules[summaryPath];
    if (moduleName == null) {
      throw StateError('Could not find module name for library "$library" '
          'from summary path "$summaryPath".');
    }
    return moduleName;
  }

  void _finishImports(List<JS.ModuleItem> items) {
    var modules = Map<String, List<LibraryElement>>();

    for (var import in _imports.keys) {
      modules.putIfAbsent(_libraryToModule(import), () => []).add(import);
    }

    String coreModuleName;
    if (!_libraries.containsKey(coreLibrary)) {
      coreModuleName = _libraryToModule(coreLibrary);
    }
    modules.forEach((module, libraries) {
      // 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 =
          libraries.map((l) => JS.NameSpecifier(_imports[l])).toList();
      if (module == coreModuleName) {
        imports.add(JS.NameSpecifier(runtimeModule));
        imports.add(JS.NameSpecifier(_extensionSymbolsModule));
      }

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

  /// 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 _emitTypeDeclaration(TypeDefiningElement e) {
    var node = _declarationNodes.remove(e);
    if (node == null) return; // not from this module or already loaded.

    var savedElement = _currentElement;
    _currentElement = e;

    // TODO(jmesserly): this is not really the right place for this.
    // Ideally we do this per function body.
    //
    // We'll need to be consistent about when we're generating functions, and
    // only run this on the outermost function, and not any closures.
    inferNullableTypes(node);

    moduleItems.add(node.accept(this) as JS.ModuleItem);

    _currentElement = savedElement;
  }

  /// To emit top-level module items, 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(TypeDefiningElement e) {
    if (e == null) return;

    if (_topLevelClass != null && identical(_currentElement, _topLevelClass)) {
      // If the item is from our library, try to emit it now.
      _emitTypeDeclaration(e);
    }
  }

  @override
  visitCompilationUnit(CompilationUnit unit) {
    // NOTE: this method isn't the right place to initialize
    // per-compilation-unit state. Declarations can be visited out of order,
    // this is only to catch things that haven't been emitted yet.
    //
    // See _emitTypeDeclaration.
    var savedElement = _currentElement;
    _currentElement = unit.declaredElement;
    var isInternalSdk = isSdkInternalRuntime(currentLibrary);
    List<VariableDeclaration> fields;
    for (var declaration in unit.declarations) {
      if (declaration is TopLevelVariableDeclaration) {
        inferNullableTypes(declaration);
        var variables = declaration.variables.variables;
        var lazyFields =
            isInternalSdk ? _emitInternalSdkFields(variables) : variables;
        if (lazyFields.isNotEmpty) {
          (fields ??= []).addAll(lazyFields);
        }
        continue;
      }

      if (fields != null) {
        _emitTopLevelFields(fields);
        fields = null;
      }

      var element = declaration.declaredElement;
      if (element is TypeDefiningElement) {
        _emitTypeDeclaration(element);
        continue;
      }

      inferNullableTypes(declaration);
      var item = declaration.accept(this) as JS.ModuleItem;
      if (isInternalSdk && element is FunctionElement) {
        _internalSdkFunctions.add(item);
      } else {
        moduleItems.add(item);
      }
    }

    if (fields != null) _emitTopLevelFields(fields);

    _currentElement = savedElement;
    return null;
  }

  void _emitExportDirectives(CompilationUnit unit) {
    var savedElement = _currentElement;
    for (var directive in unit.directives) {
      _currentElement = directive.element;
      directive.accept(this);
    }
    _currentElement = savedElement;
  }

  @override
  visitLibraryDirective(LibraryDirective node) => null;

  @override
  visitImportDirective(ImportDirective node) {
    // We don't handle imports here.
    //
    // Instead, we collect imports whenever we need to generate a reference
    // to another library. This has the effect of collecting the actually used
    // imports.
    //
    // TODO(jmesserly): if this is a prefixed import, consider adding the prefix
    // as an alias?
    return null;
  }

  @override
  visitPartDirective(PartDirective node) => null;

  @override
  visitPartOfDirective(PartOfDirective node) => null;

  @override
  visitExportDirective(ExportDirective node) {
    ExportElement element = node.element;
    var currentLibrary = element.library;

    var currentNames = currentLibrary.publicNamespace.definedNames;
    var exportedNames =
        NamespaceBuilder().createExportNamespaceForDirective(element);

    // We only need to export main as it is the only method part of the
    // publicly exposed JS API for a library.
    // TODO(jacobr): add a library level annotation indicating that all
    // contents of a library need to be exposed to JS.
    // https://github.com/dart-lang/sdk/issues/26368
    var export = exportedNames.get('main');

    if (export is FunctionElement) {
      // Don't allow redefining names from this library.
      if (currentNames.containsKey(export.name)) return null;

      var name = _emitTopLevelName(export);
      moduleItems.add(js.statement(
          '#.# = #;', [emitLibraryName(currentLibrary), name.selector, name]));
    }
    return null;
  }

  @override
  visitAsExpression(AsExpression node) {
    Expression fromExpr = node.expression;
    var from = getStaticType(fromExpr);
    var to = node.type.type;
    var jsFrom = _visitExpression(fromExpr);

    // If the check was put here by static analysis to ensure soundness, we
    // can't skip it. This happens because of unsound covariant generics:
    //
    //      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);
    //      }
    //
    // NOTE: due to implementation details, we do not currently reify the the
    // `C<T>.add` check in CoercionReifier, so it does not reach this point;
    // rather we check for it explicitly when emitting methods and fields.
    // However we do reify the `c.f` check, so we must not eliminate it.
    var isImplicit = CoercionReifier.isImplicit(node);
    if (!isImplicit && rules.isSubtypeOf(from, to)) return jsFrom;

    // Handle implicit tearoff of the `.call` method.
    //
    // TODO(jmesserly): this is handled here rather than in CoercionReifier, in
    // hopes that we can remove that extra visit and tree cloning step (which
    // has been error prone because AstCloner isn't used much, and making
    // synthetic resolved Analyzer ASTs is difficult).
    if (isImplicit &&
        from is InterfaceType &&
        rules.acceptsFunctionType(to) &&
        !_usesJSInterop(from.element)) {
      // Dart allows an implicit coercion from an interface type to a function
      // type, via a tearoff of the `call` method.
      var callMethod = from.lookUpInheritedMethod('call');
      if (callMethod != null) {
        var callName = _emitMemberName('call', type: from, element: callMethod);
        var callTearoff = runtimeCall('bindCall(#, #)', [jsFrom, callName]);
        if (rules.isSubtypeOf(callMethod.type, to)) return callTearoff;

        // We may still need an implicit coercion as well, if another downcast
        // is involved.
        return _emitCast(to, callTearoff);
      }
    }

    // All Dart number types map to a JS double.
    if (jsTypeRep.isNumber(from) && jsTypeRep.isNumber(to)) {
      // Make sure to check when converting to int.
      if (from != types.intType && to == types.intType) {
        // TODO(jmesserly): fuse this with notNull check.
        // TODO(jmesserly): this does not correctly distinguish user casts from
        // required-for-soundness casts.
        return runtimeCall('asInt(#)', jsFrom);
      }

      // A no-op in JavaScript.
      return jsFrom;
    }

    return _emitCast(to, jsFrom, implicit: isImplicit);
  }

  JS.Expression _emitCast(DartType type, JS.Expression expr,
      {bool implicit = true}) {
    // If [type] is a top type we can omit the cast.
    if (rules.isSubtypeOf(types.objectType, type)) {
      return expr;
    }
    var code = implicit ? '#._check(#)' : '#.as(#)';
    return js.call(code, [_emitType(type), expr]);
  }

  @override
  visitIsExpression(IsExpression node) {
    // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
    JS.Expression result;
    var type = node.type.type;
    var lhs = _visitExpression(node.expression);
    var typeofName = jsTypeRep.typeFor(type).primitiveTypeOf;
    // Inline primitives other than int (which requires a Math.floor check).
    if (typeofName != null && type != types.intType) {
      result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
    } else {
      result = js.call('#.is(#)', [_emitType(type), lhs]);
    }

    if (node.notOperator != null) {
      return js.call('!#', result);
    }
    return result;
  }

  /// No-op, typedefs are emitted as their corresponding function type.
  @override
  visitFunctionTypeAlias(FunctionTypeAlias node) => null;

  /// No-op, typedefs are emitted as their corresponding function type.
  @override
  visitGenericTypeAlias(GenericTypeAlias node) => null;

  @override
  JS.Expression visitTypeName(node) => _emitTypeAnnotation(node);

  @override
  JS.Expression visitGenericFunctionType(node) => _emitTypeAnnotation(node);

  JS.Expression _emitTypeAnnotation(TypeAnnotation node) {
    var type = node.type;
    if (type == null) {
      // TODO(jmesserly): if the type fails to resolve, should we generate code
      // that throws instead?
      assert(options.unsafeForceCompile || options.replCompile);
      type = types.dynamicType;
    }
    return _emitType(type);
  }

  @override
  JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
    return _emitClassDeclaration(
        node, node.declaredElement as ClassElement, []);
  }

  @override
  JS.Statement visitClassDeclaration(ClassDeclaration node) {
    return _emitClassDeclaration(node, node.declaredElement, node.members);
  }

  JS.Statement _emitClassDeclaration(Declaration classNode,
      ClassElement classElem, List<ClassMember> members) {
    // If this class is annotated with `@JS`, then there is nothing to emit.
    if (_hasJSInteropAnnotation(classElem)) return null;

    // Generic classes will be defined inside a function that closes over the
    // type parameter. So we can use their local variable name directly.
    //
    // TODO(jmesserly): the special case for JSArray is to support its special
    // type-tagging factory constructors. Those will go away once we fix:
    // https://github.com/dart-lang/sdk/issues/31003
    var className = classElem.typeParameters.isNotEmpty
        ? (classElem == _jsArray
            ? JS.Identifier(classElem.name)
            : JS.TemporaryId(classElem.name))
        : _emitTopLevelName(classElem);

    var savedClassProperties = _classProperties;
    _classProperties = ClassPropertyModel.build(
        _extensionTypes,
        virtualFields,
        classElem,
        getClassCovariantParameters(classNode),
        _usedCovariantPrivateMembers);

    var memberMap = Map<Element, Declaration>();
    for (var m in members) {
      if (m is FieldDeclaration) {
        for (var f in m.fields.variables) {
          memberMap[f.declaredElement as FieldElement] = f;
        }
      } else {
        memberMap[m.declaredElement] = m;
      }
    }

    var jsCtors =
        _defineConstructors(classElem, className, memberMap, classNode);
    var jsMethods = _emitClassMethods(classElem, members);
    _emitSuperclassCovarianceChecks(classNode, jsMethods);

    var body = <JS.Statement>[];
    _emitSuperHelperSymbols(body);
    var deferredSupertypes = <JS.Statement>[];

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

    // Emit things that come after the ES6 `class ... { ... }`.
    var jsPeerNames = _extensionTypes.getNativePeers(classElem);
    if (jsPeerNames.length == 1 && classElem.typeParameters.isNotEmpty) {
      // Special handling for JSArray<E>
      body.add(runtimeStatement('setExtensionBaseClass(#, #.global.#)',
          [className, runtimeModule, jsPeerNames[0]]));
    }

    var finishGenericTypeTest = _emitClassTypeTests(classElem, className, body);

    _emitVirtualFieldSymbols(classElem, body);
    _emitClassSignature(classElem, className, memberMap, body);
    _initExtensionSymbols(classElem);
    if (!classElem.isMixin) {
      _defineExtensionMembers(className, body);
    }
    _emitClassMetadata(classNode.metadata, className, body);

    var classDef = JS.Statement.from(body);
    var typeFormals = classElem.typeParameters;
    if (typeFormals.isNotEmpty) {
      classDef = _defineClassTypeArguments(
          classElem, typeFormals, classDef, className, deferredSupertypes);
    } else {
      body.addAll(deferredSupertypes);
    }

    body = [classDef];
    _emitStaticFields(classElem, memberMap, body);
    if (finishGenericTypeTest != null) body.add(finishGenericTypeTest);
    for (var peer in jsPeerNames) {
      _registerExtensionType(classElem, peer, body);
    }

    _classProperties = savedClassProperties;
    return JS.Statement.from(body);
  }

  JS.Statement _emitClassTypeTests(ClassElement classElem,
      JS.Expression className, List<JS.Statement> body) {
    JS.Expression getInterfaceSymbol(ClassElement c) {
      var library = c.library;
      if (library.isDartCore || library.isDartAsync) {
        switch (c.name) {
          case 'List':
          case 'Map':
          case 'Iterable':
          case 'Future':
          case 'Stream':
          case 'StreamSubscription':
            return runtimeCall('is' + c.name);
        }
      }
      return null;
    }

    void markSubtypeOf(JS.Expression testSymbol) {
      body.add(js.statement('#.prototype[#] = true', [className, testSymbol]));
    }

    for (var iface in classElem.interfaces) {
      var prop = getInterfaceSymbol(iface.element);
      if (prop != null) markSubtypeOf(prop);
    }

    if (classElem.library.isDartCore) {
      if (classElem == objectClass) {
        // Everything is an Object.
        body.add(js.statement(
            '#.is = function is_Object(o) { return true; }', [className]));
        body.add(js.statement(
            '#.as = function as_Object(o) { return o; }', [className]));
        body.add(js.statement(
            '#._check = function check_Object(o) { return o; }', [className]));
        return null;
      }
      if (classElem == stringClass) {
        body.add(js.statement(
            '#.is = function is_String(o) { return typeof o == "string"; }',
            className));
        body.add(js.statement(
            '#.as = function as_String(o) {'
            '  if (typeof o == "string" || o == null) return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_String(o) {'
            '  if (typeof o == "string" || o == null) return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
      if (classElem == functionClass) {
        body.add(js.statement(
            '#.is = function is_Function(o) { return typeof o == "function"; }',
            className));
        body.add(js.statement(
            '#.as = function as_Function(o) {'
            '  if (typeof o == "function" || o == null) return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_Function(o) {'
            '  if (typeof o == "function" || o == null) return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
      if (classElem == intClass) {
        body.add(js.statement(
            '#.is = function is_int(o) {'
            '  return typeof o == "number" && Math.floor(o) == o;'
            '}',
            className));
        body.add(js.statement(
            '#.as = function as_int(o) {'
            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
            '    return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_int(o) {'
            '  if ((typeof o == "number" && Math.floor(o) == o) || o == null)'
            '    return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
      if (classElem == nullClass) {
        body.add(js.statement(
            '#.is = function is_Null(o) { return o == null; }', className));
        body.add(js.statement(
            '#.as = function as_Null(o) {'
            '  if (o == null) return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_Null(o) {'
            '  if (o == null) return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
      if (classElem == numClass || classElem == doubleClass) {
        body.add(js.statement(
            '#.is = function is_num(o) { return typeof o == "number"; }',
            className));
        body.add(js.statement(
            '#.as = function as_num(o) {'
            '  if (typeof o == "number" || o == null) return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_num(o) {'
            '  if (typeof o == "number" || o == null) return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
      if (classElem == boolClass) {
        body.add(js.statement(
            '#.is = function is_bool(o) { return o === true || o === false; }',
            className));
        body.add(js.statement(
            '#.as = function as_bool(o) {'
            '  if (o === true || o === false || o == null) return o;'
            '  return #.as(o, #, false);'
            '}',
            [className, runtimeModule, className]));
        body.add(js.statement(
            '#._check = function check_bool(o) {'
            '  if (o === true || o === false || o == null) return o;'
            '  return #.as(o, #, true);'
            '}',
            [className, runtimeModule, className]));
        return null;
      }
    }
    if (classElem.library.isDartAsync) {
      if (classElem == types.futureOrType.element) {
        var typeParamT = classElem.typeParameters[0].type;
        var typeT = _emitType(typeParamT);
        var futureOfT = _emitType(types.futureType.instantiate([typeParamT]));
        body.add(js.statement('''
            #.is = function is_FutureOr(o) {
              return #.is(o) || #.is(o);
            }
            ''', [className, typeT, futureOfT]));
        // TODO(jmesserly): remove the fallback to `dart.as`. It's only for the
        // _ignoreTypeFailure logic.
        body.add(js.statement('''
            #.as = function as_FutureOr(o) {
              if (o == null || #.is(o) || #.is(o)) return o;
              return #.as(o, this, false);
            }
            ''', [className, typeT, futureOfT, runtimeModule]));
        body.add(js.statement('''
            #._check = function check_FutureOr(o) {
              if (o == null || #.is(o) || #.is(o)) return o;
              return #.as(o, this, true);
            }
            ''', [className, typeT, futureOfT, runtimeModule]));
        return null;
      }
    }

    body.add(runtimeStatement('addTypeTests(#)', [className]));

    if (classElem.typeParameters.isEmpty) return null;

    // For generics, testing against the default instantiation is common,
    // so optimize that.
    var isClassSymbol = getInterfaceSymbol(classElem);
    if (isClassSymbol == null) {
      // TODO(jmesserly): we could export these symbols, if we want to mark
      // implemented interfaces for user-defined classes.
      var id = JS.TemporaryId("_is_${classElem.name}_default");
      moduleItems.add(
          js.statement('const # = Symbol(#);', [id, js.string(id.name, "'")]));
      isClassSymbol = id;
    }
    // Marking every generic type instantiation as a subtype of its default
    // instantiation.
    markSubtypeOf(isClassSymbol);

    // Define the type tests on the default instantiation to check for that
    // marker.
    var defaultInst = _emitTopLevelName(classElem);

    // Return this `addTypeTests` call so we can emit it outside of the generic
    // type parameter scope.
    return runtimeStatement('addTypeTests(#, #)', [defaultInst, isClassSymbol]);
  }

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

  void _emitSuperHelperSymbols(List<JS.Statement> body) {
    _emitSymbols(
        _superHelpers.values.map((m) => m.name as JS.TemporaryId), body);
    _superHelpers.clear();
  }

  void _emitVirtualFieldSymbols(
      ClassElement classElement, List<JS.Statement> body) {
    _classProperties.virtualFields.forEach((field, virtualField) {
      body.add(js.statement('const # = Symbol(#);',
          [virtualField, js.string('${classElement.name}.${field.name}')]));
    });
  }

  List<JS.Identifier> _emitTypeFormals(List<TypeParameterElement> typeFormals) {
    return typeFormals
        .map((t) => JS.Identifier(t.name))
        .toList(growable: false);
  }

  @override
  JS.Statement visitEnumDeclaration(EnumDeclaration node) {
    return _emitClassDeclaration(node, node.declaredElement, []);
  }

  @override
  JS.Statement visitMixinDeclaration(MixinDeclaration node) {
    return _emitClassDeclaration(node, node.declaredElement, node.members);
  }

  /// Wraps a possibly generic class in its type arguments.
  JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
      List<TypeParameterElement> formals, JS.Statement body,
      [JS.Expression className, List<JS.Statement> deferredBaseClass]) {
    assert(formals.isNotEmpty);
    var jsFormals = _emitTypeFormals(formals);
    var typeConstructor = js.call('(#) => { #; #; return #; }', [
      jsFormals,
      _typeTable.discharge(formals),
      body,
      className ?? JS.Identifier(element.name)
    ]);

    var genericArgs = [typeConstructor];
    if (deferredBaseClass != null && deferredBaseClass.isNotEmpty) {
      genericArgs.add(js.call('(#) => { #; }', [jsFormals, deferredBaseClass]));
    }

    var genericCall = runtimeCall('generic(#)', [genericArgs]);

    var genericName = _emitTopLevelNameNoInterop(element, suffix: '\$');
    return js.statement('{ # = #; # = #(); }',
        [genericName, genericCall, _emitTopLevelName(element), genericName]);
  }

  JS.Statement _emitClassStatement(
      ClassElement classElem,
      JS.Expression className,
      JS.Expression heritage,
      List<JS.Method> methods) {
    if (classElem.typeParameters.isNotEmpty) {
      return JS.ClassExpression(className as JS.Identifier, heritage, methods)
          .toStatement();
    }
    var classExpr =
        JS.ClassExpression(JS.TemporaryId(classElem.name), heritage, methods);
    return js.statement('# = #;', [className, classExpr]);
  }

  /// Like [_emitClassStatement] but emits a Dart 2.1 mixin represented by
  /// [classElem].
  ///
  /// 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(
      ClassElement classElem,
      JS.Expression className,
      JS.Expression heritage,
      List<JS.Method> methods,
      List<JS.Statement> body) {
    assert(classElem.isMixin);

    var staticMethods = methods.where((m) => m.isStatic).toList();
    var instanceMethods = methods.where((m) => !m.isStatic).toList();
    body.add(
        _emitClassStatement(classElem, className, heritage, staticMethods));

    var superclassId = JS.TemporaryId(
        classElem.superclassConstraints.map((t) => t.name).join('_'));
    var classId =
        className is JS.Identifier ? className : JS.TemporaryId(classElem.name);

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

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

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

  void _defineClass(
      ClassElement classElem,
      JS.Expression className,
      List<JS.Method> methods,
      List<JS.Statement> body,
      List<JS.Statement> deferredSupertypes) {
    if (classElem.type.isObject) {
      body.add(_emitClassStatement(classElem, className, null, methods));
      return;
    }

    JS.Expression emitDeferredType(DartType t) {
      if (t is InterfaceType && t.typeArguments.isNotEmpty) {
        _declareBeforeUse(t.element);
        return _emitGenericClassType(
            t, t.typeArguments.map(emitDeferredType).toList());
      }
      return _emitType(t, cacheType: false);
    }

    bool shouldDefer(DartType t) {
      var visited = Set<DartType>();
      bool defer(DartType t) {
        if (classElem == t.element) return true;
        if (t.isObject) return false;
        if (t is ParameterizedType) {
          if (!visited.add(t)) return false;
          if (t.typeArguments.any(defer)) return true;
          if (t is InterfaceType) {
            var e = t.element;
            if (e.mixins.any(defer)) return true;
            var supertype = e.supertype;
            return supertype != null && defer(supertype);
          }
        }
        return false;
      }

      return defer(t);
    }

    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.element) ?? _emitType(t, cacheType: false);
    }

    getBaseClass(int count) {
      var base = emitDeferredType(classElem.type);
      while (--count >= 0) {
        base = js.call('#.__proto__', [base]);
      }
      return base;
    }

    var supertype = classElem.isMixin ? types.objectType : classElem.supertype;
    var hasUnnamedSuper = _hasUnnamedConstructor(supertype.element);

    void emitMixinConstructors(JS.Expression className, [InterfaceType mixin]) {
      var supertype = classElem.supertype;
      JS.Statement mixinCtor;
      if (mixin != null && _hasUnnamedConstructor(mixin.element)) {
        mixinCtor = js.statement('#.#.call(this);', [
          emitClassRef(mixin),
          _usesMixinNew(mixin.element)
              ? runtimeCall('mixinNew')
              : _constructorName('')
        ]);
      }

      for (var ctor in supertype.constructors) {
        var jsParams = _emitParametersForElement(ctor);
        var ctorBody = <JS.Statement>[];
        if (mixinCtor != null) ctorBody.add(mixinCtor);
        if (ctor.name != '' || hasUnnamedSuper) {
          ctorBody
              .add(_emitSuperConstructorCall(className, ctor.name, jsParams));
        }
        body.add(_addConstructorToClass(
            className, ctor.name, JS.Fun(jsParams, JS.Block(ctorBody))));
      }
    }

    var savedTopLevel = _topLevelClass;
    _topLevelClass = classElem;

    // Unroll mixins.
    var mixinLength = classElem.mixins.length;
    if (shouldDefer(supertype)) {
      deferredSupertypes.add(runtimeStatement('setBaseClass(#, #)', [
        getBaseClass(isMixinAliasClass(classElem) ? 0 : mixinLength),
        emitDeferredType(supertype),
      ]));
      supertype = fillDynamicTypeArgsForClass(supertype);
    }
    var baseClass = emitClassRef(supertype);

    // TODO(jmesserly): conceptually we could use isMixinApplication, however,
    // avoiding the extra level of nesting is only required if the class itself
    // is a valid mixin.
    if (isMixinAliasClass(classElem)) {
      // Given `class C = Object with M [implements I1, I2 ...];`
      // The resulting class C should work as a mixin.
      body.add(_emitClassStatement(classElem, className, baseClass, []));

      var m = classElem.mixins.single;
      bool deferMixin = shouldDefer(m);
      var mixinBody = deferMixin ? deferredSupertypes : body;
      var mixinClass = deferMixin ? emitDeferredType(m) : emitClassRef(m);
      var classExpr = deferMixin ? getBaseClass(0) : className;

      mixinBody
          .add(runtimeStatement('applyMixin(#, #)', [classExpr, mixinClass]));

      _topLevelClass = savedTopLevel;

      if (methods.isNotEmpty) {
        // However we may need to add some methods to this class that call
        // `super` such as covariance checks.
        //
        // We do this with the following pattern:
        //
        //     applyMixin(C, class C$ extends M { <methods>  });
        mixinBody.add(runtimeStatement('applyMixin(#, #)', [
          classExpr,
          JS.ClassExpression(
              JS.TemporaryId(classElem.name), mixinClass, methods)
        ]));
      }

      emitMixinConstructors(className, m);
      return;
    }

    for (int i = 0; i < mixinLength; i++) {
      var m = classElem.mixins[i];

      var mixinString = classElem.supertype.name + '_' + m.name;
      var mixinClassName = JS.TemporaryId(mixinString);
      var mixinId = JS.TemporaryId(mixinString + '\$');
      var mixinClassExpression =
          JS.ClassExpression(mixinClassName, baseClass, []);
      // Bind the mixin class to a name to workaround a V8 bug with es6 classes
      // and anonymous function names.
      // TODO(leafp:) Eliminate this once the bug is fixed:
      // https://bugs.chromium.org/p/v8/issues/detail?id=7069
      var mixinClassDef =
          js.statement("const # = #", [mixinId, mixinClassExpression]);
      body.add(mixinClassDef);
      // Add constructors

      emitMixinConstructors(mixinId, m);
      hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(m.element);

      if (shouldDefer(m)) {
        deferredSupertypes.add(runtimeStatement('applyMixin(#, #)',
            [getBaseClass(mixinLength - i), emitDeferredType(m)]));
      } else {
        body.add(
            runtimeStatement('applyMixin(#, #)', [mixinId, emitClassRef(m)]));
      }

      baseClass = mixinId;
    }

    _topLevelClass = savedTopLevel;

    if (classElem.isMixin) {
      // TODO(jmesserly): we could make this more efficient, as this creates
      // an extra unnecessary class. But it's the easiest way to handle the
      // current system.
      _emitMixinStatement(classElem, className, baseClass, methods, body);
    } else {
      body.add(_emitClassStatement(classElem, className, baseClass, methods));
    }

    if (classElem.isMixinApplication) emitMixinConstructors(className);
  }

  /// 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.Method> _emitNativeFieldAccessors(FieldDeclaration node) {
    // 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.Method>[];
    if (!node.isStatic) {
      for (var decl in node.fields.variables) {
        var field = decl.declaredElement as FieldElement;
        var name = getAnnotationName(field, isJSName) ?? field.name;
        // Generate getter
        var fn = JS.Fun([], js.block('{ return this.#; }', [name]));
        var method =
            JS.Method(_declareMemberName(field.getter), fn, isGetter: true);
        jsMethods.add(method);

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

  List<JS.Method> _emitClassMethods(
      ClassElement classElem, List<ClassMember> memberNodes) {
    var type = classElem.type;
    var virtualFields = _classProperties.virtualFields;

    var jsMethods = <JS.Method>[];
    bool hasJsPeer = _extensionTypes.isNativeClass(classElem);
    bool hasIterator = false;

    if (type.isObject) {
      // Dart does not use ES6 constructors.
      // Add an error to catch any invalid usage.
      jsMethods
          .add(JS.Method(_propertyName('constructor'), js.fun(r'''function() {
                  throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
                      ".new(...)` to create a Dart object");
              }''', [runtimeModule, runtimeModule])));
    } else if (classElem.isEnum) {
      // Generate Enum.toString()
      var fields = classElem.fields.where((f) => f.type == type).toList();
      var mapMap = List<JS.Property>(fields.length);
      for (var i = 0; i < fields.length; ++i) {
        mapMap[i] = JS.Property(
            js.number(i), js.string('${type.name}.${fields[i].name}'));
      }
      jsMethods.add(JS.Method(
          _declareMemberName(types.objectType.getMethod('toString')),
          js.fun('function() { return #[this.index]; }',
              JS.ObjectInitializer(mapMap, multiline: true))));
    }

    for (var m in memberNodes) {
      if (m is ConstructorDeclaration) {
        if (m.factoryKeyword != null &&
            m.externalKeyword == null &&
            m.body is! NativeFunctionBody) {
          jsMethods.add(_emitFactoryConstructor(m));
        }
      } else if (m is MethodDeclaration) {
        jsMethods.add(_emitMethodDeclaration(m));

        if (m.declaredElement is PropertyAccessorElement) {
          jsMethods.add(_emitSuperAccessorWrapper(m, type));
        }

        if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
          hasIterator = true;
          jsMethods.add(_emitIterable(type));
        }
      } else if (m is FieldDeclaration) {
        if (_extensionTypes.isNativeClass(classElem)) {
          jsMethods.addAll(_emitNativeFieldAccessors(m));
          continue;
        }
        if (m.isStatic) continue;
        for (VariableDeclaration field in m.fields.variables) {
          if (virtualFields.containsKey(field.declaredElement)) {
            jsMethods.addAll(_emitVirtualFieldAccessor(field));
          }
        }
      }
    }

    jsMethods.addAll(_classProperties.mockMembers.values
        .map((e) => _implementMockMember(e, type)));

    // 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 && _implementsIterable(type)) {
      jsMethods.add(_emitIterable(type));
    }

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

    return jsMethods.where((m) => m != null).toList();
  }

  void _emitSuperclassCovarianceChecks(
      Declaration node, List<JS.Method> methods) {
    var covariantParams = getSuperclassCovariantParameters(node);
    if (covariantParams == null) return;

    for (var member in covariantParams
        .map((p) => p.enclosingElement as ExecutableElement)
        .toSet()) {
      var name = _declareMemberName(member);
      if (member is PropertyAccessorElement) {
        var param =
            covariantParams.lookup(member.parameters[0]) as ParameterElement;
        methods.add(JS.Method(
            name,
            js.fun('function(x) { return super.# = #; }',
                [name, _emitCast(param.type, JS.Identifier('x'))]),
            isSetter: true));
        methods.add(JS.Method(
            name, js.fun('function() { return super.#; }', [name]),
            isGetter: true));
      } else if (member is MethodElement) {
        var type = member.type;

        var body = <JS.Statement>[];
        _emitCovarianceBoundsCheck(type.typeFormals, covariantParams, body);

        var typeFormals = _emitTypeFormals(type.typeFormals);
        var jsParams = List<JS.Parameter>.from(typeFormals);
        bool foundNamedParams = false;
        for (var param in member.parameters) {
          param = covariantParams.lookup(param) as ParameterElement;

          if (param == null) continue;
          if (param.kind == ParameterKind.NAMED) {
            foundNamedParams = true;

            var name = _propertyName(param.name);
            body.add(js.statement('if (# in #) #;', [
              name,
              namedArgumentTemp,
              _emitCast(param.type, JS.PropertyAccess(namedArgumentTemp, name))
            ]));
          } else {
            var jsParam = _emitParameter(param);
            jsParams.add(jsParam);

            if (param.kind == ParameterKind.POSITIONAL) {
              body.add(js.statement('if (# !== void 0) #;',
                  [jsParam, _emitCast(param.type, jsParam)]));
            } else {
              body.add(_emitCast(param.type, jsParam).toStatement());
            }
          }
        }

        if (foundNamedParams) jsParams.add(namedArgumentTemp);

        if (typeFormals.isEmpty) {
          body.add(js.statement('return super.#(#);', [name, jsParams]));
        } else {
          body.add(js.statement(
              'return super.#(#)(#);', [name, typeFormals, jsParams]));
        }
        var fn = JS.Fun(jsParams, JS.Block(body));
        methods.add(JS.Method(name, fn));
      } else {
        throw StateError(
            'unable to generate a covariant check for element: `$member` '
            '(${member.runtimeType})');
      }
    }
  }

  /// Emits a Dart factory constructor to a JS static method.
  JS.Method _emitFactoryConstructor(ConstructorDeclaration node) {
    if (isUnsupportedFactoryConstructor(node)) return null;

    var element = node.declaredElement;
    var name = _constructorName(element.name);
    JS.Fun fun;

    var savedFunction = _currentFunction;
    _currentFunction = node.body;

    var redirect = node.redirectedConstructor;
    if (redirect != null) {
      // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz;

      var newKeyword = redirect.staticElement.isFactory ? '' : 'new';
      // Pass along all arguments verbatim, and let the callee handle them.
      // TODO(jmesserly): we'll need something different once we have
      // rest/spread support, but this should work for now.
      var params = _emitParameters(node.parameters?.parameters);

      fun = JS.Fun(
          params,
          JS.Block([
            js.statement('return $newKeyword #(#)',
                [visitConstructorName(redirect), params])
              ..sourceInformation = _nodeStart(redirect)
          ]));
    } else {
      // Normal factory constructor
      var body = <JS.Statement>[];
      var init = _emitArgumentInitializers(element, node.parameters);
      if (init != null) body.add(init);
      body.add(_visitStatement(node.body));

      var params = _emitParameters(node.parameters?.parameters);
      fun = JS.Fun(params, JS.Block(body));
    }

    _currentFunction = savedFunction;

    return JS.Method(name, fun, isStatic: true)
      ..sourceInformation = _functionEnd(node);
  }

  /// Given a class C that implements method M from interface I, but does not
  /// declare M, this will generate an implementation that forwards to
  /// noSuchMethod.
  ///
  /// For example:
  ///
  ///     class Cat {
  ///       bool eatFood(String food) => true;
  ///     }
  ///     class MockCat implements Cat {
  ///        noSuchMethod(Invocation invocation) => 3;
  ///     }
  ///
  /// It will generate an `eatFood` that looks like:
  ///
  ///     eatFood(food) {
  ///       return core.bool.as(this.noSuchMethod(
  ///           new dart.InvocationImpl.new('eatFood', [food])));
  ///     }
  JS.Method _implementMockMember(ExecutableElement method, InterfaceType type) {
    var invocationProps = <JS.Property>[];
    addProperty(String name, JS.Expression value) {
      invocationProps.add(JS.Property(js.string(name), value));
    }

    var typeParams = _emitTypeFormals(method.type.typeFormals);
    var fnArgs = List<JS.Parameter>.from(typeParams);
    var args = _emitParametersForElement(method);
    fnArgs.addAll(args);
    var argInit = _emitArgumentInitializers(method);

    if (method is PropertyAccessorElement) {
      if (method.isGetter) {
        addProperty('isGetter', js.boolean(true));
      } else {
        assert(method.isSetter);
        addProperty('isSetter', js.boolean(true));
      }
    } else {
      addProperty('isMethod', js.boolean(true));
    }

    var positionalArgs = args;
    var namedParameterTypes = method.type.namedParameterTypes;
    if (namedParameterTypes.isNotEmpty) {
      // Sort the names to match dart2js order.
      var sortedNames = (namedParameterTypes.keys.toList())..sort();
      var named = sortedNames
          .map((n) => JS.Property(_propertyName(n), JS.Identifier(n)));
      addProperty('namedArguments', JS.ObjectInitializer(named.toList()));
      positionalArgs.removeLast();
    }
    if (typeParams.isNotEmpty) {
      addProperty('typeArguments', JS.ArrayInitializer(typeParams));
    }

    var fnBody =
        js.call('this.noSuchMethod(new #.InvocationImpl.new(#, [#], #))', [
      runtimeModule,
      _declareMemberName(method),
      args,
      JS.ObjectInitializer(invocationProps)
    ]);

    fnBody = _emitCast(method.returnType, fnBody);

    var fnBlock = argInit != null
        ? JS.Block([argInit, fnBody.toReturn()])
        : fnBody.toReturn().toBlock();

    return JS.Method(
        _declareMemberName(method,
            useExtension: _extensionTypes.isNativeClass(type.element)),
        JS.Fun(fnArgs, fnBlock),
        isGetter: method is PropertyAccessorElement && method.isGetter,
        isSetter: method is PropertyAccessorElement && method.isSetter,
        isStatic: false);
  }

  /// 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.Method> _emitVirtualFieldAccessor(VariableDeclaration field) {
    var element = field.declaredElement as FieldElement;
    var virtualField = _classProperties.virtualFields[element];
    var result = <JS.Method>[];
    var name = _declareMemberName(element.getter);

    var mocks = _classProperties.mockMembers;
    if (!mocks.containsKey(element.name)) {
      var getter = js.fun('function() { return this[#]; }', [virtualField]);
      result.add(JS.Method(name, getter, isGetter: true)
        ..sourceInformation = _functionSpan(field.name));
    }

    if (!mocks.containsKey(element.name + '=')) {
      var args = field.isFinal ? [JS.Super(), name] : [JS.This(), virtualField];

      var setter = element.setter;
      var covariantParams = _classProperties.covariantParameters;
      JS.Expression value = JS.Identifier('value');
      if (setter != null &&
          covariantParams != null &&
          covariantParams.contains(setter.parameters[0])) {
        value = _emitCast(setter.parameters[0].type, value);
      }
      args.add(value);

      result.add(JS.Method(name, js.fun('function(value) { #[#] = #; }', args),
          isSetter: true)
        ..sourceInformation = _functionSpan(field.name));
    }

    return result;
  }

  /// 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.Method _emitSuperAccessorWrapper(
      MethodDeclaration member, InterfaceType type) {
    var accessorElement = member.declaredElement as PropertyAccessorElement;
    var field = accessorElement.variable;
    if (!field.isSynthetic || accessorElement.isAbstract) return null;

    // Generate a corresponding virtual getter / setter.
    var name = _declareMemberName(accessorElement);
    if (member.isGetter) {
      var setter = field.setter;
      if ((setter == null || setter.isAbstract) &&
          _classProperties.inheritedSetters.contains(field.name)) {
        // Generate a setter that forwards to super.
        var fn = js.fun('function(value) { super[#] = value; }', [name]);
        return JS.Method(name, fn, isSetter: true);
      }
    } else {
      var getter = field.getter;
      if ((getter == null || getter.isAbstract) &&
          _classProperties.inheritedGetters.contains(field.name)) {
        // Generate a getter that forwards to super.
        var fn = js.fun('function() { return super[#]; }', [name]);
        return JS.Method(name, fn, isGetter: true);
      }
    }
    return null;
  }

  bool _implementsIterable(InterfaceType t) =>
      t.interfaces.any((i) => i.element.type == types.iterableType);

  /// 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.Method _emitIterable(InterfaceType t) {
    // 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 = t.lookUpGetterInSuperclass('iterator', t.element.library);
    if (parent != null) return null;
    var parentType = findSupertype(t, _implementsIterable);
    if (parentType != null) return null;

    if (t.element.source.isInSystemLibrary &&
        t.methods.any((m) => getJSExportName(m) == 'Symbol.iterator')) {
      return null;
    }

    // Otherwise, emit the adapter method, which wraps the Dart iterator in
    // an ES6 iterator.
    return JS.Method(
        js.call('Symbol.iterator'),
        js.call('function() { return new #.JsIterator(this.#); }',
            [runtimeModule, _emitMemberName('iterator', type: t)]) as JS.Fun);
  }

  JS.Expression _instantiateAnnotation(Annotation node) {
    var element = node.element;
    if (element is ConstructorElement) {
      return _emitInstanceCreationExpression(
          element,
          element.returnType as InterfaceType,
          () => _emitArgumentList(node.arguments),
          isConst: true);
    } else {
      return _visitExpression(node.name);
    }
  }

  void _registerExtensionType(
      ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
    var className = _emitTopLevelName(classElem);
    if (jsTypeRep.isPrimitive(classElem.type)) {
      body.add(
          runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
    }
    body.add(runtimeStatement(
        'registerExtension(#, #)', [js.string(jsPeerName), className]));
  }

  /// Defines all constructors for this class as ES5 constructors.
  List<JS.Statement> _defineConstructors(
      ClassElement classElem,
      JS.Expression className,
      Map<Element, Declaration> memberMap,
      Declaration classNode) {
    var body = <JS.Statement>[];
    if (classElem.isMixinApplication) {
      // We already handled this when we defined the class.
      return body;
    }

    addConstructor(String name, JS.Expression jsCtor) {
      body.add(_addConstructorToClass(className, name, jsCtor));
    }

    if (classElem.isEnum) {
      addConstructor('', js.call('function(x) { this.index = x; }'));
      return body;
    }

    var fields = List<VariableDeclaration>.from(memberMap.values.where((m) =>
        m is VariableDeclaration &&
        !(m.declaredElement as FieldElement).isStatic));

    // Iff no constructor is specified for a class C, it implicitly has a
    // default constructor `C() : super() {}`, unless C is class Object.
    var defaultCtor = classElem.unnamedConstructor;
    if (defaultCtor != null && defaultCtor.isSynthetic) {
      assert(classElem.constructors.length == 1,
          'default constructor only if no other constructors');
      var superCall = _emitSuperConstructorCallIfNeeded(classElem, className);
      var ctorBody = <JS.Statement>[_initializeFields(fields)];
      if (superCall != null) ctorBody.add(superCall);

      addConstructor(
          '',
          JS.Fun([], JS.Block(ctorBody))
            ..sourceInformation = _functionEnd(classNode));
      return body;
    }

    for (var element in classElem.constructors) {
      if (element.isSynthetic || element.isFactory || element.isExternal) {
        continue;
      }
      var ctor = memberMap[element] as ConstructorDeclaration;
      if (ctor.body is NativeFunctionBody) continue;

      addConstructor(element.name, _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(classElem)) {
      body.add(
          js.statement('(#[#] = function() { # }).prototype = #.prototype;', [
        className,
        runtimeCall('mixinNew'),
        [_initializeFields(fields)],
        className
      ]));
    }

    return body;
  }

  /// 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.
  bool _usesMixinNew(ClassElement mixin) {
    return (mixin.supertype?.isObject ?? false) &&
        mixin.constructors.every((c) =>
            c.isSynthetic && c.name != '' || c.isFactory || c.isExternal);
  }

  JS.Statement _addConstructorToClass(
      JS.Expression className, String name, JS.Expression jsCtor) {
    jsCtor = defineValueOnClass(className, _constructorName(name), jsCtor);
    return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
  }

  /// Emits static fields for a class, and initialize them eagerly if possible,
  /// otherwise define them as lazy properties.
  void _emitStaticFields(ClassElement classElem,
      Map<Element, Declaration> members, List<JS.Statement> body) {
    if (classElem.isEnum) {
      // Emit enum static fields
      var type = classElem.type;
      void addField(FieldElement e, JS.Expression value) {
        body.add(defineValueOnClass(_emitStaticClassName(classElem),
                _declareMemberName(e.getter), value)
            .toStatement());
      }

      int index = 0;
      var values = <JS.Expression>[];
      for (var f in classElem.fields) {
        if (f.type != type) continue;
        // static const E id_i = const E(i);
        values.add(JS.PropertyAccess(
            _emitStaticClassName(classElem), _declareMemberName(f.getter)));
        var enumValue = runtimeCall('const(new (#.#)(#))', [
          _emitConstructorAccess(type),
          _constructorName(''),
          js.number(index++)
        ]);
        addField(f, enumValue);
      }
      // static const List<E> values = const <E>[id_0 . . . id_n−1];
      addField(classElem.getField('values'), _emitConstList(type, values));
      return;
    }

    var lazyStatics = classElem.fields
        .where((f) => f.isStatic && !f.isSynthetic)
        .map((f) => members[f] as VariableDeclaration)
        .toList();
    if (lazyStatics.isNotEmpty) {
      body.add(_emitLazyFields(_emitStaticClassName(classElem), lazyStatics,
          (e) => _emitStaticMemberName(e.name, e)));
    }
  }

  void _emitClassMetadata(List<Annotation> metadata, JS.Expression className,
      List<JS.Statement> body) {
    // Metadata
    if (options.emitMetadata && metadata.isNotEmpty) {
      body.add(js.statement('#[#.metadata] = () => [#];',
          [className, runtimeModule, metadata.map(_instantiateAnnotation)]));
    }
  }

  /// Ensure `dartx.` symbols we will use are present.
  void _initExtensionSymbols(ClassElement classElem) {
    if (_extensionTypes.hasNativeSubtype(classElem.type) ||
        classElem.type.isObject) {
      for (var members in [classElem.methods, classElem.accessors]) {
        for (var m in members) {
          if (!m.isAbstract && !m.isStatic && m.isPublic) {
            _declareMemberName(m, useExtension: true);
          }
        }
      }
    }
  }

  /// If a concrete class implements one of our extensions, we might need to
  /// add forwarders.
  void _defineExtensionMembers(
      JS.Expression className, List<JS.Statement> body) {
    void emitExtensions(String helperName, Iterable<String> extensions) {
      if (extensions.isEmpty) return;

      var names = extensions
          .map((e) => _propertyName(JS.memberNameForDartMember(e)))
          .toList();
      body.add(js.statement('#.#(#, #);', [
        runtimeModule,
        helperName,
        className,
        JS.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(ClassElement classElem, JS.Expression className,
      Map<Element, Declaration> annotatedMembers, List<JS.Statement> body) {
    if (classElem.interfaces.isNotEmpty ||
        classElem.superclassConstraints.isNotEmpty) {
      var interfaces = classElem.interfaces.toList()
        ..addAll(classElem.superclassConstraints);

      body.add(js.statement('#[#.implements] = () => [#];',
          [className, runtimeModule, interfaces.map(_emitType)]));
    }

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

      if (!name.startsWith('Static')) {
        var proto = classElem.type.isObject
            ? js.call('Object.create(null)')
            : runtimeCall('get${name}s(#.__proto__)', [className]);
        elements.insert(0, JS.Property(_propertyName('__proto__'), proto));
      }
      body.add(runtimeStatement('set${name}Signature(#, () => #)', [
        className,
        JS.ObjectInitializer(elements, multiline: elements.length > 1)
      ]));
    }

    var mockMembers = _classProperties.mockMembers;

    {
      var extMembers = _classProperties.extensionMethods;
      var staticMethods = <JS.Property>[];
      var instanceMethods = <JS.Property>[];
      var classMethods = classElem.methods.where((m) => !m.isAbstract).toList();
      for (var m in mockMembers.values) {
        if (m is MethodElement) classMethods.add(m);
      }

      for (var method in classMethods) {
        var isStatic = method.isStatic;
        if (isStatic && !options.emitMetadata) continue;

        var name = method.name;
        var reifiedType = _getMemberRuntimeType(method);
        var memberOverride =
            classElem.type.lookUpMethodInSuperclass(name, currentLibrary);
        // 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 needsSignature = memberOverride == null ||
            memberOverride.isAbstract ||
            _getMemberRuntimeType(memberOverride) != reifiedType;

        if (needsSignature) {
          var annotationNode = annotatedMembers[method] as MethodDeclaration;

          var type = _emitAnnotatedFunctionType(
              reifiedType, annotationNode?.metadata,
              parameters: annotationNode?.parameters?.parameters);
          var property = JS.Property(_declareMemberName(method), type);
          if (isStatic) {
            staticMethods.add(property);
          } else {
            instanceMethods.add(property);
            if (extMembers.contains(name)) {
              instanceMethods.add(JS.Property(
                  _declareMemberName(method, useExtension: true), type));
            }
          }
        }
      }

      emitSignature('Method', instanceMethods);
      emitSignature('StaticMethod', staticMethods);
    }

    {
      var extMembers = _classProperties.extensionAccessors;
      var staticGetters = <JS.Property>[];
      var instanceGetters = <JS.Property>[];
      var staticSetters = <JS.Property>[];
      var instanceSetters = <JS.Property>[];

      var classAccessors = classElem.accessors
          .where((m) => !m.isAbstract && !m.isSynthetic)
          .toList();
      for (var m in mockMembers.values) {
        if (m is PropertyAccessorElement) classAccessors.add(m);
      }

      for (var accessor in classAccessors) {
        // Static getters/setters cannot be called with dynamic dispatch, nor
        // can they be torn off.
        var isStatic = accessor.isStatic;
        if (isStatic && !options.emitMetadata) continue;

        var name = accessor.name;
        var isGetter = accessor.isGetter;
        var memberOverride = isGetter
            ? classElem.type.lookUpGetterInSuperclass(name, currentLibrary)
            : classElem.type.lookUpSetterInSuperclass(name, currentLibrary);

        var reifiedType = accessor.type;
        // 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 needsSignature = memberOverride == null ||
            memberOverride.isAbstract ||
            memberOverride.type != reifiedType;

        if (needsSignature) {
          var annotationNode = annotatedMembers[accessor] as MethodDeclaration;
          var type = _emitAnnotatedResult(
              _emitType(
                  isGetter
                      ? reifiedType.returnType
                      : reifiedType.parameters[0].type,
                  cacheType: false),
              annotationNode?.metadata);

          var property = JS.Property(_declareMemberName(accessor), type);
          if (isStatic) {
            (isGetter ? staticGetters : staticSetters).add(property);
          } else {
            var accessors = isGetter ? instanceGetters : instanceSetters;
            accessors.add(property);
            if (extMembers.contains(accessor.variable.name)) {
              accessors.add(JS.Property(
                  _declareMemberName(accessor, useExtension: true), type));
            }
          }
        }
      }
      emitSignature('Getter', instanceGetters);
      emitSignature('Setter', instanceSetters);
      emitSignature('StaticGetter', staticGetters);
      emitSignature('StaticSetter', staticSetters);
    }

    {
      var instanceFields = <JS.Property>[];
      var staticFields = <JS.Property>[];

      for (var field in classElem.fields) {
        if (field.isSynthetic && !classElem.isEnum) continue;
        // Only instance fields need to be saved for dynamic dispatch.
        var isStatic = field.isStatic;
        if (isStatic && !options.emitMetadata) continue;

        var fieldNode = annotatedMembers[field] as VariableDeclaration;
        var metadata = fieldNode != null
            ? (fieldNode.parent.parent as FieldDeclaration).metadata
            : null;

        var memberName = _declareMemberName(field.getter);
        var fieldSig = _emitFieldSignature(field.type,
            metadata: metadata, isFinal: field.isFinal);
        (isStatic ? staticFields : instanceFields)
            .add(JS.Property(memberName, fieldSig));
      }
      emitSignature('Field', instanceFields);
      emitSignature('StaticField', staticFields);
    }

    if (options.emitMetadata) {
      var constructors = <JS.Property>[];
      for (var ctor in classElem.constructors) {
        var annotationNode = annotatedMembers[ctor] as ConstructorDeclaration;
        var memberName = _constructorName(ctor.name);
        var type = _emitAnnotatedFunctionType(
            ctor.type, annotationNode?.metadata,
            parameters: annotationNode?.parameters?.parameters);
        constructors.add(JS.Property(memberName, type));
      }

      emitSignature('Constructor', constructors);
    }

    // Add static property dart._runtimeType to Object.
    //
    // All other Dart classes will (statically) inherit this property.
    if (classElem == objectClass) {
      body.add(runtimeStatement('lazyFn(#, () => #.#)',
          [className, emitLibraryName(coreLibrary), 'Type']));
    }
  }

  JS.Expression _emitConstructor(ConstructorDeclaration node,
      List<VariableDeclaration> fields, JS.Expression className) {
    var params = _emitParameters(node.parameters?.parameters);

    var savedFunction = _currentFunction;
    _currentFunction = node.body;

    var savedSuperAllowed = _superAllowed;
    _superAllowed = false;
    var body = _emitConstructorBody(node, fields, className);
    _superAllowed = savedSuperAllowed;
    _currentFunction = savedFunction;

    return JS.Fun(params, body)..sourceInformation = _functionEnd(node);
  }

  FunctionType _getMemberRuntimeType(ExecutableElement element) {
    // Check whether we have any covariant parameters.
    // Usually we don't, so we can use the same type.
    if (!element.parameters.any(_isCovariant)) return element.type;

    var parameters = element.parameters
        .map((p) => ParameterElementImpl.synthetic(p.name,
            _isCovariant(p) ? objectClass.type : p.type, p.parameterKind))
        .toList();

    var function = FunctionElementImpl("", -1)
      ..isSynthetic = true
      ..returnType = element.returnType
      // TODO(jmesserly): do covariant type parameter bounds also need to be
      // reified as `Object`?
      ..shareTypeParameters(element.typeParameters)
      ..parameters = parameters;
    return function.type = FunctionTypeImpl(function);
  }

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

  JS.Block _emitConstructorBody(ConstructorDeclaration node,
      List<VariableDeclaration> fields, JS.Expression className) {
    var body = <JS.Statement>[];
    ClassDeclaration cls = node.parent;

    // 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 init = _emitArgumentInitializers(node.declaredElement, node.parameters);
    if (init != null) body.add(init);

    // Redirecting constructors: these are not allowed to have initializers,
    // and the redirecting ctor invocation runs before field initializers.
    for (var init in node.initializers) {
      if (init is RedirectingConstructorInvocation) {
        body.add(_emitRedirectingConstructor(init, className));
        return JS.Block(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));

    var superCall = node.initializers.firstWhere(
        (i) => i is SuperConstructorInvocation,
        orElse: () => null) as SuperConstructorInvocation;

    // 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 superCallArgs =
        superCall != null ? _emitArgumentList(superCall.argumentList) : null;
    var jsSuper = _emitSuperConstructorCallIfNeeded(cls.declaredElement,
        className, superCall?.staticElement, superCallArgs);
    if (jsSuper != null) {
      if (superCall != null) jsSuper.sourceInformation = _nodeStart(superCall);
      body.add(jsSuper);
    }

    body.add(_emitFunctionScopedBody(node.body, node.declaredElement));
    return JS.Block(body);
  }

  JS.Statement _emitRedirectingConstructor(
      RedirectingConstructorInvocation node, JS.Expression className) {
    var ctor = node.staticElement;
    // We can't dispatch to the constructor with `this.new` as that might hit a
    // derived class constructor with the same name.
    return js.statement('#.#.call(this, #);', [
      className,
      _constructorName(ctor.name),
      _emitArgumentList(node.argumentList)
    ]);
  }

  JS.Statement _emitSuperConstructorCallIfNeeded(
      ClassElement element, JS.Expression className,
      [ConstructorElement superCtor, List<JS.Expression> args]) {
    // Get the supertype's unnamed constructor.
    superCtor ??= element.supertype?.element?.unnamedConstructor;
    if (superCtor == null) {
      assert(element.type.isObject ||
          element.isMixin ||
          options.unsafeForceCompile);
      return null;
    }

    // We can skip the super call if it's empty. Typically this happens for
    // things that extend Object.
    if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) {
      return null;
    }

    return _emitSuperConstructorCall(className, superCtor.name, args);
  }

  JS.Statement _emitSuperConstructorCall(
      JS.Expression className, String name, List<JS.Expression> args) {
    return js.statement('#.__proto__.#.call(this, #);',
        [className, _constructorName(name), args ?? []]);
  }

  bool _hasUnnamedSuperConstructor(ClassElement e) {
    var supertype = e.supertype;
    // Object or mixin declaration.
    if (supertype == null) return false;
    if (_hasUnnamedConstructor(supertype.element)) return true;
    for (var mixin in e.mixins) {
      if (_hasUnnamedConstructor(mixin.element)) return true;
    }
    return false;
  }

  bool _hasUnnamedConstructor(ClassElement e) {
    if (e.type.isObject) return false;
    var ctor = e.unnamedConstructor;
    if (ctor == null) return false;
    if (!ctor.isSynthetic) return true;
    if (e.fields.any((f) => !f.isStatic && !f.isSynthetic)) return true;
    return _hasUnnamedSuperConstructor(e);
  }

  /// 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.Statement _initializeFields(List<VariableDeclaration> fieldDecls,
      [ConstructorDeclaration ctor]) {
    Set<FieldElement> ctorFields;
    emitFieldInit(FieldElement f, Expression initializer, AstNode hoverInfo) {
      ctorFields?.add(f);
      var access =
          _classProperties.virtualFields[f] ?? _declareMemberName(f.getter);
      var jsInit = _visitInitializer(initializer, f);
      return jsInit
          .toAssignExpression(js.call('this.#', [access])
            ..sourceInformation = _nodeSpan(hoverInfo))
          .toStatement();
    }

    var body = <JS.Statement>[];
    if (ctor != null) {
      ctorFields = HashSet<FieldElement>();

      // Run constructor parameter initializers such as `this.foo`
      for (var p in ctor.parameters.parameters) {
        var element = p.declaredElement;
        if (element is FieldFormalParameterElement) {
          body.add(emitFieldInit(element.field, p.identifier, p.identifier));
        }
      }

      // Run constructor field initializers such as `: foo = bar.baz`
      for (var init in ctor.initializers) {
        if (init is ConstructorFieldInitializer) {
          var field = init.fieldName;
          var element = field.staticElement as FieldElement;
          body.add(emitFieldInit(element, init.expression, field));
        } else if (init is AssertInitializer) {
          body.add(_emitAssert(init.condition, init.message));
        }
      }
    }

    // Run field initializers if needed.
    //
    // We can skip fields where the initializer doesn't have side effects
    // (for example, it's a literal value such as implicit `null`) and where
    // there's another explicit initialization (either in the initializer list
    // like `field = value`, or via a `this.field` parameter).
    var fieldInit = <JS.Statement>[];
    for (var field in fieldDecls) {
      var f = field.declaredElement as FieldElement;
      if (f.isStatic) continue;
      if (ctorFields != null &&
          ctorFields.contains(f) &&
          _constants.isFieldInitConstant(field)) {
        continue;
      }
      fieldInit.add(emitFieldInit(f, field.initializer, field.name));
    }
    // Run field initializers before the other ones.
    fieldInit.addAll(body);
    return JS.Statement.from(fieldInit);
  }

  /// Emits argument initializers, which handles optional/named args, as well
  /// as generic type checks needed due to our covariance.
  JS.Statement _emitArgumentInitializers(ExecutableElement element,
      [FormalParameterList parameterNodes]) {
    var body = <JS.Statement>[];

    _emitCovarianceBoundsCheck(
        element.typeParameters, _classProperties?.covariantParameters, body);
    for (int i = 0, n = element.parameters.length; i < n; i++) {
      var param = element.parameters[i];
      var paramNode =
          parameterNodes != null ? parameterNodes.parameters[i] : null;
      var jsParam = _emitParameter(param);
      if (parameterNodes != null) {
        jsParam.sourceInformation = _nodeStart(paramNode.identifier);
      }

      if (param.isOptional) {
        JS.Expression defaultValue;
        if (paramNode != null) {
          var paramDefault = (paramNode as DefaultFormalParameter).defaultValue;
          if (paramDefault == null) {
            defaultValue = JS.LiteralNull();
          } else if (_isJSUndefined(paramDefault)) {
            defaultValue = null;
          } else {
            defaultValue = _visitExpression(paramDefault);
          }
        } else {
          // TODO(jmesserly): it would be cleaner to emit the initializer
          // Expression AST, but it does not seem to be fully resolved
          // (for example, a list literal will not have the list type).
          //
          // So instead we use constant evaluation and emit the constant.
          defaultValue = _emitDartObject(param.computeConstantValue());
        }
        if (param.isNamed) {
          // Parameters will be passed using their real names, not the (possibly
          // renamed) local variable.
          var paramName = js.string(param.name, "'");
          if (defaultValue != null) {
            // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming.
            body.add(js.statement('let # = # && # in # ? #.# : #;', [
              jsParam,
              namedArgumentTemp,
              paramName,
              namedArgumentTemp,
              namedArgumentTemp,
              paramName,
              defaultValue,
            ]));
          } else {
            body.add(js.statement('let # = # && #.#;', [
              jsParam,
              namedArgumentTemp,
              namedArgumentTemp,
              paramName,
            ]));
          }
        } else {
          assert(param.isOptionalPositional);
          if (defaultValue != null) {
            body.add(js.statement(
                'if (# === void 0) # = #;', [jsParam, jsParam, defaultValue]));
          }
        }
      }

      if (_isCovariant(param)) {
        body.add(_emitCast(param.type, jsParam).toStatement());
      }
      if (_annotatedNullCheck(param)) {
        body.add(_nullParameterCheck(jsParam));
      }
    }
    return body.isEmpty ? null : JS.Statement.from(body);
  }

  bool _isCovariant(ParameterElement p) {
    return p.isCovariant ||
        (_classProperties?.covariantParameters?.contains(p) ?? false);
  }

  bool _isJSUndefined(Expression expr) {
    expr = expr is AsExpression ? expr.expression : expr;
    if (expr is Identifier) {
      var element = expr.staticElement;
      return isSdkInternalRuntime(element.library) &&
          element.name == 'undefined';
    }
    return false;
  }

  JS.Fun _emitNativeFunctionBody(MethodDeclaration node) {
    String name = getAnnotationName(node.declaredElement, isJSAnnotation) ??
        node.name.name;
    if (node.isGetter) {
      return JS.Fun([], js.block('{ return this.#; }', [name]));
    } else if (node.isSetter) {
      var params = _emitParameters(node.parameters?.parameters);
      return JS.Fun(params, js.block('{ this.# = #; }', [name, params.last]));
    } else {
      return js.fun(
          'function (...args) { return this.#.apply(this, args); }', name);
    }
  }

  JS.Method _emitMethodDeclaration(MethodDeclaration node) {
    if (node.isAbstract) {
      return null;
    }

    JS.Fun fn;
    if (node.externalKeyword != null || node.body is NativeFunctionBody) {
      if (node.isStatic) {
        // TODO(vsm): Do we need to handle this case?
        return null;
      }
      fn = _emitNativeFunctionBody(node);
    } else {
      fn = _emitFunction(node.declaredElement, node.parameters, node.body);
    }

    return JS.Method(_declareMemberName(node.declaredElement), fn,
        isGetter: node.isGetter,
        isSetter: node.isSetter,
        isStatic: node.isStatic)
      ..sourceInformation = _functionEnd(node);
  }

  @override
  JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
    assert(node.parent is CompilationUnit);

    if (node.externalKeyword != null ||
        node.functionExpression.body is NativeFunctionBody) {
      return null;
    }

    if (node.isGetter || node.isSetter) {
      PropertyAccessorElement element = node.declaredElement;
      var pairAccessor = node.isGetter
          ? element.correspondingSetter
          : element.correspondingGetter;

      var jsCode = _emitTopLevelProperty(node);
      var props = <JS.Method>[jsCode];
      if (pairAccessor != null) {
        // If we have a getter/setter pair, they need to be defined together.
        // If this is the first one, save the generated code for later.
        // If this is the second one, get the saved code and emit both.
        var pairCode = _deferredProperties.remove(pairAccessor);
        if (pairCode == null) {
          _deferredProperties[element] = jsCode;
          return null;
        }
        props.add(pairCode);
      }
      return runtimeStatement(
          'copyProperties(#, { # })', [emitLibraryName(currentLibrary), props]);
    }

    var body = <JS.Statement>[];
    var fn = _emitFunctionExpression(node.functionExpression);

    if (currentLibrary.source.isInSystemLibrary &&
        _isInlineJSFunction(node.functionExpression)) {
      fn = JS.simplifyPassThroughArrowFunCallBody(fn);
    }
    fn.sourceInformation = _functionEnd(node);

    var element = resolutionMap.elementDeclaredByFunctionDeclaration(node);
    var nameExpr = _emitTopLevelName(element);
    body.add(js.statement('# = #', [nameExpr, fn]));
    // Function types of top-level/static functions are only needed when
    // dart:mirrors is enabled.
    // TODO(jmesserly): do we even need this for mirrors, since statics are not
    // commonly reflected on?
    if (options.emitMetadata && _reifyFunctionType(element)) {
      body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true)
          .toStatement());
    }

    return JS.Statement.from(body);
  }

  bool _isInlineJSFunction(FunctionExpression functionExpression) {
    var body = functionExpression.body;
    if (body is ExpressionFunctionBody) {
      return _isJSInvocation(body.expression);
    } else if (body is BlockFunctionBody) {
      var statements = body.block.statements;
      if (statements.length == 1) {
        var stat = statements[0];
        if (stat is ReturnStatement) {
          return _isJSInvocation(stat.expression);
        }
      }
    }
    return false;
  }

  bool _isJSInvocation(Expression expr) =>
      expr is MethodInvocation && isInlineJS(expr.methodName.staticElement);

  JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
    var name = node.name.name;
    return JS.Method(
        _propertyName(name), _emitFunctionExpression(node.functionExpression),
        isGetter: node.isGetter, isSetter: node.isSetter)
      ..sourceInformation = _functionEnd(node);
  }

  bool _executesAtTopLevel(AstNode node) {
    var ancestor = node.getAncestor((n) =>
        n is FunctionBody ||
        n is FieldDeclaration && n.staticKeyword == null ||
        n is ConstructorDeclaration && n.constKeyword == null);
    return ancestor == null;
  }

  /// Whether the expression for [type] can be evaluated at this point in the JS
  /// module.
  ///
  /// Types cannot be evaluated if they depend on something that hasn't been
  /// defined yet. For example:
  ///
  ///     C foo() => null;
  ///     class C {}
  ///
  /// If we're emitting the type information for `foo`, we cannot refer to `C`
  /// yet, so we must evaluate foo's type lazily.
  bool _canEmitTypeAtTopLevel(DartType type) {
    if (type is FunctionType) {
      // Generic functions are always safe to emit, because they're lazy until
      // type arguments are applied.
      if (type.typeFormals.isNotEmpty) return true;

      return _canEmitTypeAtTopLevel(type.returnType) &&
          type.optionalParameterTypes.every(_canEmitTypeAtTopLevel) &&
          type.namedParameterTypes.values.every(_canEmitTypeAtTopLevel) &&
          type.normalParameterTypes.every(_canEmitTypeAtTopLevel);
    }
    if (type.isDynamic || type.isVoid || type.isBottom) return true;
    if (type is ParameterizedType &&
        !type.typeArguments.every(_canEmitTypeAtTopLevel)) {
      return false;
    }
    return !_declarationNodes.containsKey(type.element);
  }

  JS.Expression _emitFunctionTagged(JS.Expression fn, FunctionType type,
      {bool topLevel = false}) {
    var lazy = topLevel && !_canEmitTypeAtTopLevel(type);
    var typeRep = _emitFunctionType(type, lazy: lazy);
    return runtimeCall(lazy ? 'lazyFn(#, #)' : 'fn(#, #)', [fn, typeRep]);
  }

  /// Emits an arrow FunctionExpression node.
  ///
  /// This should be used for all places in Dart's AST where FunctionExpression
  /// appears and the function is actually in an Expression context. These
  /// correspond to arrow functions in Dart.
  ///
  /// Contrast with [_emitFunctionExpression].
  @override
  JS.Expression visitFunctionExpression(FunctionExpression node) {
    assert(node.parent is! FunctionDeclaration &&
        node.parent is! MethodDeclaration);
    var fn = _emitArrowFunction(node);
    if (!_reifyFunctionType(node.declaredElement)) return fn;
    return _emitFunctionTagged(fn, getStaticType(node) as FunctionType,
        topLevel: _executesAtTopLevel(node));
  }

  JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
    var f = _emitFunction(node.declaredElement, node.parameters, node.body);
    JS.Node body = f.body;

    // Simplify `=> { return e; }` to `=> e`
    if (body is JS.Block) {
      JS.Block block = body;
      if (block.statements.length == 1) {
        JS.Statement s = block.statements[0];
        if (s is JS.Return && s.value != null) body = s.value;
      }
    }

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

  /// Emits a non-arrow FunctionExpression node.
  ///
  /// This should be used for all places in Dart's AST where FunctionExpression
  /// appears but the function is not actually in an Expression context, such
  /// as methods, properties, and top-level functions.
  ///
  /// Contrast with [visitFunctionExpression].
  JS.Fun _emitFunctionExpression(FunctionExpression node) {
    return _emitFunction(node.declaredElement, node.parameters, node.body);
  }

  JS.Fun _emitFunction(ExecutableElement element,
      FormalParameterList parameters, FunctionBody body) {
    FunctionType type = element.type;

    // normal function (sync), vs (sync*, async, async*)
    var isSync = !(element.isAsynchronous || element.isGenerator);
    var formals = _emitParameters(parameters?.parameters);
    var typeFormals = _emitTypeFormals(type.typeFormals);
    if (_reifyGeneric(element)) formals.insertAll(0, typeFormals);

    super.enterFunction(
        element.name,
        formals,
        () => isPotentiallyMutated(
            body, parameters.parameters.last.declaredElement));

    JS.Block code = isSync
        ? _emitFunctionBody(element, parameters, body)
        : JS.Block([
            _emitGeneratorFunction(element, parameters, body).toReturn()
              ..sourceInformation = _nodeStart(body)
          ]);

    code = super.exitFunction(element.name, formals, code);
    return JS.Fun(formals, code);
  }

  JS.Block _emitFunctionBody(ExecutableElement element,
      FormalParameterList parameters, FunctionBody body) {
    var savedFunction = _currentFunction;
    _currentFunction = body;

    var initArgs = _emitArgumentInitializers(element, parameters);
    var block = _emitFunctionScopedBody(body, element);

    if (initArgs != null) block = JS.Block([initArgs, block]);

    _currentFunction = savedFunction;

    if (block.isScope) {
      // TODO(jmesserly: JS AST printer does not understand the need to emit a
      // nested scoped block in a JS function. So we need to add a non-scoped
      // wrapper to ensure it gets printed.
      block = JS.Block([block]);
    }
    return block;
  }

  JS.Block _emitFunctionScopedBody(
      FunctionBody body, ExecutableElement element) {
    var block = body.accept(this) as JS.Block;
    if (element.parameters.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 =
          HashSet<String>.from(element.parameters.map((e) => e.name));
      return block.toScopedBlock(parameterNames);
    }
    return block;
  }

  void _emitCovarianceBoundsCheck(List<TypeParameterElement> typeFormals,
      Set<Element> covariantParams, List<JS.Statement> body) {
    if (covariantParams == null) return;
    for (var t in typeFormals) {
      t = covariantParams.lookup(t) as TypeParameterElement;
      if (t != null) {
        body.add(runtimeStatement('checkTypeBound(#, #, #)',
            [_emitType(t.type), _emitType(t.bound), _propertyName(t.name)]));
      }
    }
  }

  JS.Expression _emitGeneratorFunction(ExecutableElement element,
      FormalParameterList parameters, FunctionBody body) {
    // Transforms `sync*` `async` and `async*` function bodies
    // using ES6 generators.

    var returnType = _getExpectedReturnType(element);

    emitGeneratorFn(List<JS.Parameter> jsParams, [JS.TemporaryId asyncStar]) {
      var savedSuperAllowed = _superAllowed;
      var savedController = _asyncStarController;
      _superAllowed = false;
      _asyncStarController = asyncStar;

      // Visit the body with our async* controller set.
      //
      // TODO(jmesserly): this will emit argument initializers (for default
      // values) inside the generator function body. Is that the best place?
      var jsBody = _emitFunctionBody(element, parameters, body);
      var genFn = JS.Fun(jsParams, jsBody, isGenerator: true);

      // Name the function if possible, to get better stack traces.
      var name = element.name;
      JS.Expression gen = genFn;
      if (name.isNotEmpty) {
        gen = JS.NamedFunction(
            JS.TemporaryId(JS.friendlyNameForDartOperator[name] ?? name),
            genFn);
      }
      gen.sourceInformation = _functionEnd(body);
      if (JS.This.foundIn(gen)) gen = js.call('#.bind(this)', gen);

      _superAllowed = savedSuperAllowed;
      _asyncStarController = savedController;
      return gen;
    }

    if (element.isSynchronous) {
      // `sync*` wraps a generator in a Dart Iterable<E>:
      //
      // function name(<args>) {
      //   return new SyncIterator<E>(() => (function* name(<mutated args>) {
      //     <body>
      //   }(<mutated args>));
      // }
      //
      // In the body of a `sync*`, `yield` is generated simply as `yield`.
      //
      // We need to include all <mutated args> as parameters of the generator,
      // so each `.iterator` starts with the same initial values.
      //
      // We also need to ensure the correct `this` is available.
      //
      // In the future, we might be able to simplify this, see:
      // https://github.com/dart-lang/sdk/issues/28320
      assert(element.isGenerator);

      var params = parameters?.parameters;

      var jsParams = _emitParameters(
          params?.where((p) => isPotentiallyMutated(body, p.declaredElement)));

      var gen = emitGeneratorFn(jsParams);
      if (jsParams.isNotEmpty) gen = js.call('() => #(#)', [gen, jsParams]);

      var syncIterable = _emitType(syncIterableType.instantiate([returnType]));
      return js.call('new #.new(#)', [syncIterable, gen]);
    }

    if (element.isGenerator) {
      // `async*` uses the `_AsyncStarImpl<T>` helper class. The generator
      // callback takes an instance of this class.
      //
      // `yield` is specially generated inside `async*` by visitYieldStatement.
      // `await` is generated as `yield`.
      //
      // _AsyncStarImpl has an example of the generated code.
      var asyncStarParam = JS.TemporaryId('stream');
      var gen = emitGeneratorFn([asyncStarParam], asyncStarParam);

      var asyncStarImpl = asyncStarImplType.instantiate([returnType]);
      return js.call('new #.new(#).stream', [_emitType(asyncStarImpl), gen]);
    }

    // `async` works similar to `sync*`:
    //
    // function name(<args>) {
    //   return async.async(E, function* name() {
    //     <body>
    //   });
    // }
    //
    // In the body of an `async`, `await` is generated simply as `yield`.
    var gen = emitGeneratorFn([]);
    var dartAsync = types.futureType.element.library;
    return js.call('#.async(#, #)',
        [emitLibraryName(dartAsync), _emitType(returnType), gen]);
  }

  @override
  JS.Statement visitFunctionDeclarationStatement(
      FunctionDeclarationStatement node) {
    var func = node.functionDeclaration;
    if (func.isGetter || func.isSetter) {
      return js.comment('Unimplemented function get/set statement: $node');
    }

    var fn = _emitFunctionExpression(func.functionExpression);

    var name = _emitVariableDef(func.name);
    JS.Statement declareFn;
    if (JS.This.foundIn(fn)) {
      declareFn = js.statement('const # = #.bind(this);', [name, fn]);
    } else {
      declareFn = JS.FunctionDeclaration(name, fn);
    }
    var element = func.declaredElement;
    if (_reifyFunctionType(element)) {
      declareFn = JS.Block(
          [declareFn, _emitFunctionTagged(name, element.type).toStatement()]);
    }
    return declareFn;
  }

  /// Emits a simple identifier, including handling an inferred generic
  /// function instantiation.
  @override
  JS.Expression visitSimpleIdentifier(SimpleIdentifier node,
      [PrefixedIdentifier prefix]) {
    var typeArgs = _getTypeArgs(node.staticElement, node.staticType);
    var simpleId = _emitSimpleIdentifier(node, prefix)
      ..sourceInformation = _nodeSpan(node);
    if (prefix != null &&
        // Check that the JS AST is for a Dart property and not JS interop.
        simpleId is JS.PropertyAccess &&
        simpleId.receiver is JS.Identifier) {
      // Attach the span to the library prefix.
      simpleId.receiver.sourceInformation = _nodeSpan(prefix.prefix);
    }
    if (typeArgs == null) return simpleId;
    return runtimeCall('gbind(#, #)', [simpleId, typeArgs]);
  }

  /// Emits a simple identifier, handling implicit `this` as well as
  /// going through the qualified library name if necessary, but *not* handling
  /// inferred generic function instantiation.
  JS.Expression _emitSimpleIdentifier(SimpleIdentifier node,
      [PrefixedIdentifier prefix]) {
    var accessor = resolutionMap.staticElementForIdentifier(node);
    if (accessor == null) {
      return _throwUnsafe('unresolved identifier: ' + (node.name ?? '<null>'));
    }

    // Get the original declaring element. If we had a property accessor, this
    // indirects back to a (possibly synthetic) field.
    var element = accessor;
    if (accessor is PropertyAccessorElement) element = accessor.variable;

    // If this is one of our compiler's temporary variables, return its JS form.
    if (element is TemporaryVariableElement) {
      return element.jsVariable;
    }

    // As an optimization, directly emit simple constants.
    // (This is not required for correctness.)
    if (element is VariableElement && element.isStatic && element.isConst) {
      var value = element.computeConstantValue() as DartObjectImpl;
      // TODO(jmesserly): value should always be non-null unless the program has
      // errors. However constants seem to be missing in some cases, see:
      // https://github.com/dart-lang/sdk/issues/33885
      //
      // This may be an Analyzer bug. This workaround prevents a compiler crash
      // until we can track down the root cause (or migrate to CFE+Kernel).
      //
      // If the constant is not a primitive (or we fail to evaluate it), then
      // we can fall through and emit a reference to it at runtime.
      //
      // TODO(jmesserly): avoid inlining strings depending on their length.
      if (value != null && value.isBoolNumStringOrNull) {
        var result = _emitDartObject(value);
        if (result != null) return result;
      }
    }

    // type literal
    if (element is TypeDefiningElement) {
      _declareBeforeUse(element);
      var typeName = _emitTypeDefiningElement(element);

      // If the type is a type literal expression in Dart code, wrap the raw
      // runtime type in a "Type" instance.
      if (!_isInForeignJS && _isTypeLiteral(node)) {
        typeName = runtimeCall('wrapType(#)', typeName);
      }

      return typeName;
    }

    // library member
    if (element.enclosingElement is CompilationUnitElement) {
      return _emitLibraryMemberElement(accessor, prefix ?? node);
    }

    // Unqualified class member. This could mean implicit-this, or implicit
    // call to a static from the same class.
    if (element is ClassMemberElement && element is! ConstructorElement) {
      return _emitClassMemberElement(element, accessor, prefix ?? node);
    }

    if (element is ParameterElement) {
      return _emitParameter(element);
    }

    return JS.Identifier(element.name);
  }

  JS.Expression _emitLibraryMemberElement(Element element, Expression node) {
    var result = _emitTopLevelName(element);
    if (element is FunctionElement && _reifyTearoff(element, node)) {
      return _emitFunctionTagged(result, element.type);
    }
    return result;
  }

  JS.Expression _emitClassMemberElement(
      ClassMemberElement element, Element accessor, Expression node) {
    bool isStatic = element.isStatic;
    var classElem = element.enclosingElement;
    var type = classElem.type;
    var member = _emitMemberName(element.name,
        isStatic: isStatic, type: type, element: accessor);

    // A static native element should just forward directly to the
    // JS type's member.
    //
    // TODO(jmesserly): this code path seems broken. It doesn't exist
    // elsewhere, such as [_emitAccess], so it will only take affect for
    // unqualified static access inside of the the same class.
    //
    // If we want this feature to work, we'll need to implement it in the
    // standard [_emitStaticClassName] code path, which will need to know the
    // member we're calling so it can determine whether to use the Dart class
    // name or the native JS class name.
    if (isStatic && _isExternal(element)) {
      var nativeName = _extensionTypes.getNativePeers(classElem);
      if (nativeName.isNotEmpty) {
        var memberName = getAnnotationName(element, isJSName) ?? member;
        return runtimeCall('global.#.#', [nativeName[0], memberName]);
      }
    }

    // For instance members, we add implicit-this.
    // For method tear-offs, we ensure it's a bound method.
    var target = isStatic ? _emitStaticClassName(classElem) : JS.This();
    if (element is MethodElement && _reifyTearoff(element, node)) {
      if (isStatic) {
        // TODO(jmesserly): we could tag static/top-level function types once
        // in the module initialization, rather than at the point where they
        // escape.
        return _emitFunctionTagged(
            JS.PropertyAccess(target, member), element.type);
      }
      return runtimeCall('bind(#, #)', [target, member]);
    }
    return JS.PropertyAccess(target, member);
  }

  JS.Identifier _emitVariableDef(SimpleIdentifier id) {
    return JS.Identifier(id.name)..sourceInformation = _nodeStart(id);
  }

  /// Returns `true` if the type name referred to by [node] is used in a
  /// position where it should evaluate as a type literal -- an object of type
  /// Type.
  bool _isTypeLiteral(SimpleIdentifier node) {
    var parent = node.parent;

    // Static member call.
    if (parent is MethodInvocation || parent is PropertyAccess) return false;

    // An expression like "a.b".
    if (parent is PrefixedIdentifier) {
      // In "a.b", "b" may be a type literal, but "a", is not.
      if (node != parent.identifier) return false;

      // If the prefix expression is itself used as an invocation, like
      // "a.b.c", then "b" is not a type literal.
      var grand = parent.parent;
      if (grand is MethodInvocation || grand is PropertyAccess) return false;

      return true;
    }

    // In any other context, it's a type literal.
    return true;
  }

  JS.Identifier _emitParameter(ParameterElement element,
      {bool declaration = false}) {
    // initializing formal parameter, e.g. `Point(this._x)`
    // TODO(jmesserly): type ref is not attached in this case.
    if (element.isInitializingFormal && element.isPrivate) {
      /// Rename private names so they don't shadow the private field symbol.
      /// The renamer would handle this, but it would prefer to rename the
      /// temporary used for the private symbol. Instead rename the parameter.
      return _initializingFormalTemps.putIfAbsent(
          element, () => JS.TemporaryId(element.name.substring(1)));
    }

    return JS.Identifier(element.name);
  }

  List<Annotation> _parameterMetadata(FormalParameter p) =>
      (p is NormalFormalParameter)
          ? p.metadata
          : (p as DefaultFormalParameter).parameter.metadata;

  // Wrap a result - usually a type - with its metadata.  The runtime is
  // responsible for unpacking this.
  JS.Expression _emitAnnotatedResult(
      JS.Expression result, List<Annotation> metadata) {
    if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
      result = JS.ArrayInitializer(
          [result]..addAll(metadata.map(_instantiateAnnotation)));
    }
    return result;
  }

  JS.Expression _emitFieldSignature(DartType type,
      {List<Annotation> metadata, bool isFinal = true}) {
    var args = [_emitType(type)];
    if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
      args.add(
          JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList()));
    }
    return runtimeCall(isFinal ? 'finalFieldType(#)' : 'fieldType(#)', [args]);
  }

  JS.ArrayInitializer _emitTypeNames(
      List<DartType> types, List<FormalParameter> parameters,
      {bool cacheType = true}) {
    var result = <JS.Expression>[];
    for (int i = 0; i < types.length; ++i) {
      var metadata =
          parameters != null ? _parameterMetadata(parameters[i]) : null;
      var typeName = _emitType(types[i], cacheType: cacheType);
      result.add(_emitAnnotatedResult(typeName, metadata));
    }
    return JS.ArrayInitializer(result);
  }

  JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types,
      {bool cacheType = true}) {
    var properties = <JS.Property>[];
    types.forEach((name, type) {
      var key = _propertyName(name);
      var value = _emitType(type, cacheType: cacheType);
      properties.add(JS.Property(key, value));
    });
    return JS.ObjectInitializer(properties);
  }

  /// Emit the pieces of a function type, as an array of return type,
  /// regular args, and optional/named args.
  JS.Expression _emitFunctionType(FunctionType type,
      {List<FormalParameter> parameters,
      bool cacheType = true,
      bool lazy = false}) {
    var parameterTypes = type.normalParameterTypes;
    var optionalTypes = type.optionalParameterTypes;
    var namedTypes = type.namedParameterTypes;
    var rt = _emitType(type.returnType, cacheType: cacheType);

    var ra = _emitTypeNames(parameterTypes, parameters, cacheType: cacheType);

    List<JS.Expression> typeParts;
    if (namedTypes.isNotEmpty) {
      assert(optionalTypes.isEmpty);
      // TODO(vsm): Pass in annotations here as well.
      var na = _emitTypeProperties(namedTypes, cacheType: cacheType);
      typeParts = [rt, ra, na];
    } else if (optionalTypes.isNotEmpty) {
      assert(namedTypes.isEmpty);
      var oa = _emitTypeNames(
          optionalTypes, parameters?.sublist(parameterTypes.length),
          cacheType: cacheType);
      typeParts = [rt, ra, oa];
    } else {
      typeParts = [rt, ra];
    }

    JS.Expression fullType;
    String helperCall;
    var typeFormals = type.typeFormals;
    if (typeFormals.isNotEmpty) {
      var tf = _emitTypeFormals(typeFormals);

      addTypeFormalsAsParameters(List<JS.Expression> elements) {
        var names = _typeTable.discharge(typeFormals);
        return names.isEmpty
            ? js.call('(#) => [#]', [tf, elements])
            : js.call('(#) => {#; return [#];}', [tf, names, elements]);
      }

      typeParts = [addTypeFormalsAsParameters(typeParts)];

      helperCall = 'gFnType(#)';
      // If any explicit bounds were passed, emit them.
      if (typeFormals.any((t) => t.bound != null)) {
        var bounds = typeFormals
            .map((t) => _emitType(t.type.bound, cacheType: cacheType))
            .toList();
        typeParts.add(addTypeFormalsAsParameters(bounds));
      }
    } else {
      helperCall = 'fnType(#)';
    }
    fullType = runtimeCall(helperCall, [typeParts]);
    if (!cacheType) return fullType;
    return _typeTable.nameFunctionType(type, fullType, lazy: lazy);
  }

  JS.Expression _emitAnnotatedFunctionType(
      FunctionType type, List<Annotation> metadata,
      {List<FormalParameter> parameters}) {
    var result =
        _emitFunctionType(type, parameters: parameters, cacheType: false);
    return _emitAnnotatedResult(result, metadata);
  }

  /// Emits an expression that lets you access statics on a [type] from code.
  JS.Expression _emitConstructorAccess(DartType type) {
    return _emitJSInterop(type.element) ?? _emitType(type);
  }

  /// Emits an expression that lets you access statics on an [c] from code.
  JS.Expression _emitStaticClassName(ClassElement c) {
    _declareBeforeUse(c);
    return _emitTopLevelName(c);
  }

  /// Emits a Dart [type] into code.
  ///
  /// If [cacheType] is true, then the type will be cached for the module.
  JS.Expression _emitType(DartType type, {bool cacheType = true}) {
    // The void and dynamic types are not defined in core.
    if (type.isVoid) {
      return runtimeCall('void');
    } else if (type.isDynamic) {
      return runtimeCall('dynamic');
    } else if (type.isBottom) {
      return runtimeCall('bottom');
    }

    var element = type.element;
    if (element is TypeDefiningElement) {
      _declareBeforeUse(element);
    }

    // Type parameters don't matter as JS interop types cannot be reified.
    // We have to use lazy JS types because until we have proper module
    // loading for JS libraries bundled with Dart libraries, we will sometimes
    // need to load Dart libraries before the corresponding JS libraries are
    // actually loaded.
    // Given a JS type such as:
    //     @JS('google.maps.Location')
    //     class Location { ... }
    // We can't emit a reference to MyType because the JS library that defines
    // it may be loaded after our code. So for now, we use a special lazy type
    // object to represent MyType.
    // Anonymous JS types do not have a corresponding concrete JS type so we
    // have to use a helper to define them.
    if (_isObjectLiteral(element)) {
      return runtimeCall('anonymousJSType(#)', js.escapedString(element.name));
    }
    var jsName = _getJSNameWithoutGlobal(element);
    if (jsName != null) {
      return runtimeCall('lazyJSType(() => #, #)',
          [_emitJSInteropForGlobal(jsName), js.escapedString(jsName)]);
    }

    var name = type.name;
    if (type is TypeParameterType) {
      _typeParamInConst?.add(type);
      return JS.Identifier(name);
    }

    if (type is ParameterizedType) {
      if (type is FunctionType) {
        return _emitFunctionType(type, cacheType: cacheType);
      }
      var args = type.typeArguments;
      List<JS.Expression> jsArgs;
      if (args.any((a) => !a.isDynamic)) {
        jsArgs = args.map((x) => _emitType(x, cacheType: cacheType)).toList();
      }
      if (jsArgs != null) {
        var typeRep = _emitGenericClassType(type, jsArgs);
        return cacheType ? _typeTable.nameType(type, typeRep) : typeRep;
      }
    }

    return _emitTopLevelNameNoInterop(element);
  }

  /// Emits the raw type corresponding to the [element].
  JS.Expression _emitTypeDefiningElement(TypeDefiningElement element) {
    return _emitType(fillDynamicTypeArgsForElement(element));
  }

  JS.Expression _emitGenericClassType(
      ParameterizedType t, List<JS.Expression> typeArgs) {
    var genericName = _emitTopLevelNameNoInterop(t.element, suffix: '\$');
    return js.call('#(#)', [genericName, typeArgs]);
  }

  JS.PropertyAccess _emitTopLevelName(Element e, {String suffix = ''}) {
    return _emitJSInterop(e) ?? _emitTopLevelNameNoInterop(e, suffix: suffix);
  }

  JS.PropertyAccess _emitTopLevelNameNoInterop(Element e,
      {String suffix = ''}) {
    return JS.PropertyAccess(
        emitLibraryName(e.library), _emitTopLevelMemberName(e, 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.Expression _emitTopLevelMemberName(Element e, {String suffix = ''}) {
    var name = getJSExportName(e) ?? _getElementName(e);
    return _propertyName(name + suffix);
  }

  @override
  JS.Expression visitAssignmentExpression(AssignmentExpression node) {
    var left = node.leftHandSide;
    var right = node.rightHandSide;
    if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
    var op = node.operator.lexeme;
    assert(op.endsWith('='));
    op = op.substring(0, op.length - 1); // remove trailing '='
    return _emitOpAssign(left, right, op, node.staticElement, context: node);
  }

  JS.MetaLet _emitOpAssign(
      Expression left, Expression right, String op, MethodElement element,
      {Expression context}) {
    if (op == '??') {
      // Desugar `l ??= r` as ((x) => x == null ? l = r : x)(l)
      // Note that if `x` contains subexpressions, we need to ensure those
      // are also evaluated only once. This is similar to desugaring for
      // postfix expressions like `i++`.

      // Handle the left hand side, to ensure each of its subexpressions are
      // evaluated only once.
      var vars = <JS.MetaLetVariable, JS.Expression>{};
      var x = _bindLeftHandSide(vars, left, context: left);
      // Capture the result of evaluating the left hand side in a temp.
      var t = _bindValue(vars, 't', x, context: x);
      return JS.MetaLet(vars, [
        js.call('# == null ? # : #',
            [_visitExpression(t), _emitSet(x, right), _visitExpression(t)])
      ]);
    }

    // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions
    // (for example, x is IndexExpression) we evaluate those once.
    var vars = <JS.MetaLetVariable, JS.Expression>{};
    var lhs = _bindLeftHandSide(vars, left, context: context);
    // TODO(leafp): The element for lhs here will be the setter element
    // instead of the getter element if lhs is a property access. This
    // interferes with nullability analysis.
    Expression inc = ast.binaryExpression(lhs, op, right)
      ..staticElement = element
      ..staticType = getStaticType(lhs);

    var castTo = getImplicitOperationCast(left);
    if (castTo != null) inc = CoercionReifier.castExpression(inc, castTo);
    return JS.MetaLet(vars, [_emitSet(lhs, inc)]);
  }

  JS.Expression _emitSet(Expression left, Expression right) {
    if (left is IndexExpression) {
      var target = _getTarget(left);
      if (_useNativeJsIndexer(target.staticType)) {
        return js.call('#[#] = #', [
          _visitExpression(target),
          _visitExpression(left.index),
          _visitExpression(right)
        ]);
      }
      return _emitOperatorCall(
          target, '[]=', [left.index, right], left.staticElement);
    }

    if (left is SimpleIdentifier) {
      return _emitSetSimpleIdentifier(left, right);
    }

    Expression target = null;
    SimpleIdentifier id;
    if (left is PropertyAccess) {
      if (left.operator.lexeme == '?.') {
        return _emitNullSafeSet(left, right);
      }
      target = _getTarget(left);
      id = left.propertyName;
    } else if (left is PrefixedIdentifier) {
      if (isLibraryPrefix(left.prefix)) {
        return _emitSet(left.identifier, right);
      }
      target = left.prefix;
      id = left.identifier;
    } else {
      assert(false);
    }

    if (isDynamicInvoke(target)) {
      return runtimeCall('dput$_replSuffix(#, #, #)', [
        _visitExpression(target),
        _emitMemberName(id.name),
        _visitExpression(right)
      ]);
    }

    var accessor = id.staticElement;
    if (accessor is PropertyAccessorElement) {
      var field = accessor.variable;
      if (field is FieldElement) {
        return _emitSetField(right, field, _visitExpression(target), id);
      }
    }

    return _badAssignment('Unhandled assignment', left, right);
  }

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

  JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) {
    // TODO(sra): We should get here only for compiler bugs or weirdness due to
    // --unsafe-force-compile. Once those paths have been addressed, throw at
    // compile time.
    assert(options.unsafeForceCompile);
    return runtimeCall('throwUnimplementedError((#, #, #))',
        [js.string('$lhs ='), _visitExpression(rhs), js.string(problem)]);
  }

  /// Emits assignment to a simple identifier. Handles all legal simple
  /// identifier assignment targets (local, top level library member, implicit
  /// `this` or class, etc.)
  JS.Expression _emitSetSimpleIdentifier(
      SimpleIdentifier node, Expression right) {
    JS.Expression unimplemented() {
      return _badAssignment("Unimplemented: unknown name '$node'", node, right);
    }

    var accessor = resolutionMap.staticElementForIdentifier(node);
    if (accessor == null) return unimplemented();

    // Get the original declaring element. If we had a property accessor, this
    // indirects back to a (possibly synthetic) field.
    var element = accessor;
    if (accessor is PropertyAccessorElement) element = accessor.variable;

    if (element is TypeDefiningElement) {
      _declareBeforeUse(element);
    }

    if (element is LocalVariableElement || element is ParameterElement) {
      return _emitSetLocal(element, right, node);
    }

    if (accessor is PropertyAccessorElement &&
        element.enclosingElement is CompilationUnitElement) {
      // Top level library member.
      return _emitSetTopLevel(accessor, right);
    }

    // Unqualified class member. This could mean implicit `this`, or implicit
    // static from the same class.
    if (element is FieldElement) {
      return _emitSetField(right, element, JS.This(), node);
    }

    // We should not get here.
    return unimplemented();
  }

  /// Emits assignment to a simple local variable or parameter.
  JS.Expression _emitSetLocal(Element element, Expression rhs, AstNode left) {
    JS.Expression target;
    if (element is TemporaryVariableElement) {
      // If this is one of our compiler's temporary variables, use its JS form.
      target = element.jsVariable;
    } else if (element is ParameterElement) {
      target = _emitParameter(element);
    } else {
      target = JS.Identifier(element.name);
    }
    target.sourceInformation = _nodeSpan(left);
    return _visitExpression(rhs).toAssignExpression(target);
  }

  /// Emits assignment to library scope element [element].
  JS.Expression _emitSetTopLevel(
      PropertyAccessorElement element, Expression rhs) {
    return _visitExpression(rhs).toAssignExpression(_emitTopLevelName(element));
  }

  /// Emits assignment to a static field element or property.
  JS.Expression _emitSetField(Expression right, FieldElement field,
      JS.Expression jsTarget, SimpleIdentifier id) {
    var classElem = field.enclosingElement;
    var isStatic = field.isStatic;
    var member = _emitMemberName(field.name,
        isStatic: isStatic, type: classElem.type, element: field.setter);
    jsTarget = isStatic
        ? (JS.PropertyAccess(_emitStaticClassName(classElem), member)
          ..sourceInformation = _nodeSpan(id))
        : _emitTargetAccess(jsTarget, member, field.setter, id);
    return _visitExpression(right).toAssignExpression(jsTarget);
  }

  JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
    // Emit `obj?.prop = expr` as:
    //
    //     (_ => _ == null ? null : _.prop = expr)(obj).
    //
    // We could use a helper, e.g.:  `nullSafeSet(e1, _ => _.v = e2)`
    //
    // However with MetaLet, we get clean code in statement or void context,
    // or when one of the expressions is stateless, which seems common.
    var vars = <JS.MetaLetVariable, JS.Expression>{};
    var left = _bindValue(vars, 'l', node.target);
    var body = js.call('# == null ? null : #', [
      _visitExpression(left),
      _emitSet(_stripNullAwareOp(node, left), right)
    ]);
    return JS.MetaLet(vars, [body]);
  }

  @override
  JS.Block visitExpressionFunctionBody(ExpressionFunctionBody node) {
    return JS.Block([_visitExpression(node.expression).toReturn()]);
  }

  @override
  JS.Block visitEmptyFunctionBody(EmptyFunctionBody node) => JS.Block([]);

  @override
  JS.Block visitBlockFunctionBody(BlockFunctionBody node) {
    return JS.Block(_visitStatementList(node.block.statements));
  }

  @override
  JS.Block visitBlock(Block node) =>
      JS.Block(_visitStatementList(node.statements), isScope: true);

  @override
  visitMethodInvocation(MethodInvocation node) {
    if (_isDeferredLoadLibrary(node.target, node.methodName)) {
      // We are calling loadLibrary() on a deferred library prefix.
      return runtimeCall('loadLibrary()');
    }

    if (node.operator?.lexeme == '?.' && isNullable(node.target)) {
      return _emitNullSafe(node);
    }

    var e = node.methodName.staticElement;
    var result = _emitForeignJS(node, e);
    if (result != null) return result;

    // Optimize some internal SDK calls.
    if (e != null &&
        isSdkInternalRuntime(e.library) &&
        node.argumentList.arguments.length == 1) {
      var firstArg = node.argumentList.arguments[0];
      if (e.name == 'getGenericClass' && firstArg is SimpleIdentifier) {
        var typeElem = firstArg.staticElement;
        if (typeElem is TypeDefiningElement &&
            typeElem.type is ParameterizedType) {
          return _emitTopLevelNameNoInterop(typeElem, suffix: '\$');
        }
      }
      if (e.name == 'unwrapType' && firstArg is SimpleIdentifier) {
        var typeElem = firstArg.staticElement;
        if (typeElem is TypeDefiningElement) {
          return _emitTypeDefiningElement(typeElem);
        }
      }
      if (e.name == 'extensionSymbol' && firstArg is StringLiteral) {
        return _getExtensionSymbolInternal(firstArg.stringValue);
      }
    }

    var target = _getTarget(node);
    if (target == null || isLibraryPrefix(target)) {
      return _emitFunctionCall(node);
    }
    if (node.methodName.name == 'call' &&
        _isDirectCallable(target.staticType)) {
      // Call methods on function types should be handled as regular function
      // invocations.
      return _emitFunctionCall(node, node.target);
    }

    return _emitMethodCall(target, node);
  }

  JS.Expression _emitTarget(Expression target, Element member, bool isStatic) {
    if (isStatic) {
      if (member is ConstructorElement) {
        return _emitConstructorAccess(member.enclosingElement.type)
          ..sourceInformation = _nodeSpan(target);
      }
      if (member is PropertyAccessorElement) {
        var field = member.variable;
        if (field is FieldElement) {
          return _emitStaticClassName(field.enclosingElement)
            ..sourceInformation = _nodeSpan(target);
        }
      }
      if (member is MethodElement) {
        return _emitStaticClassName(member.enclosingElement)
          ..sourceInformation = _nodeSpan(target);
      }
    }
    var result = _visitExpression(target);
    if (target == _cascadeTarget) {
      // Don't attach source information to a cascade target, as that would
      // result in marking the same location from different lines.
      result.sourceInformation = null;
    }
    return result;
  }

  /// Emits the [JS.PropertyAccess] for accessors or method calls to
  /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
  JS.Expression _emitTargetAccess(JS.Expression jsTarget, JS.Expression jsName,
      Element member, AstNode node) {
    JS.Expression result;
    if (!_superAllowed && jsTarget is JS.Super && member != null) {
      result = _getSuperHelper(member, jsName);
    } else {
      result = JS.PropertyAccess(jsTarget, jsName);
    }
    if (node != null) {
      // Use the full span for a cascade property so we can hover over `bar` in
      // `..bar()` and see the `bar` method.
      var cascade = _cascadeTarget;
      var parent = node.parent;
      var isCascade = cascade != null &&
          parent is Expression &&
          _getTarget(parent) == cascade;
      result.sourceInformation = isCascade ? _nodeSpan(node) : _nodeEnd(node);
    }
    return result;
  }

  JS.Expression _getSuperHelper(Element member, JS.Expression jsName) {
    var jsMethod = _superHelpers.putIfAbsent(member.name, () {
      if (member is PropertyAccessorElement) {
        var isSetter = member.isSetter;
        var fn = js.fun(
            isSetter
                ? 'function(x) { super[#] = x; }'
                : 'function() { return super[#]; }',
            [jsName]);
        return JS.Method(JS.TemporaryId(member.variable.name), fn,
            isGetter: !isSetter, isSetter: isSetter);
      } else {
        var method = member as MethodElement;
        var params =
            List<JS.Identifier>.from(_emitTypeFormals(method.typeParameters));
        for (var param in method.parameters) {
          if (param.isNamed) {
            params.add(namedArgumentTemp);
            break;
          }
          params.add(JS.Identifier(param.name));
        }

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

  JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
    var argumentList = node.argumentList;
    var args = _emitArgumentList(argumentList);
    var typeArgs = _emitInvokeTypeArguments(node);

    var type = getStaticType(target);
    var element = node.methodName.staticElement;
    bool isStatic = element is ExecutableElement && element.isStatic;
    var name = node.methodName.name;
    var jsName =
        _emitMemberName(name, type: type, isStatic: isStatic, element: element);

    if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) {
      JS.Expression jsTarget = _emitTarget(target, element, isStatic);
      if (jsTarget is JS.Super) {
        jsTarget =
            _emitTargetAccess(jsTarget, jsName, element, node.methodName);
        jsName = null;
      }
      return _emitDynamicInvoke(jsTarget, typeArgs, jsName, args, argumentList);
    }

    JS.Expression jsTarget = _emitTarget(target, element, isStatic);

    // Handle Object methods that are supported by `null`.
    if (_isObjectMethodCall(name, argumentList.arguments) &&
        isNullable(target)) {
      assert(typeArgs == null); // Object methods don't take type args.
      return runtimeCall('#(#, #)', [name, jsTarget, args]);
    }

    jsTarget = _emitTargetAccess(jsTarget, jsName, element, node.methodName);
    // Handle `o.m(a)` where `o.m` is a getter returning a class with `call`.
    if (element is PropertyAccessorElement) {
      var fromType = element.returnType;
      if (fromType is InterfaceType) {
        var callName = _getImplicitCallTarget(fromType);
        if (callName != null) {
          jsTarget = JS.PropertyAccess(jsTarget, callName);
        }
      }
    }
    var castTo = getImplicitOperationCast(node);
    if (castTo != null) {
      jsTarget = _emitCast(castTo, jsTarget);
    }
    if (typeArgs != null) args.insertAll(0, typeArgs);
    return JS.Call(jsTarget, args);
  }

  JS.Expression _emitDynamicInvoke(
      JS.Expression fn,
      List<JS.Expression> typeArgs,
      JS.Expression methodName,
      List<JS.Expression> args,
      ArgumentList argumentList) {
    var jsArgs = <Object>[fn];
    String jsCode;
    if (typeArgs != null) {
      jsArgs.add(typeArgs);
      if (methodName != null) {
        jsCode = 'dgsend$_replSuffix(#, [#], #';
        jsArgs.add(methodName);
      } else {
        jsCode = 'dgcall(#, [#]';
      }
    } else if (methodName != null) {
      jsCode = 'dsend$_replSuffix(#, #';
      jsArgs.add(methodName);
    } else {
      jsCode = 'dcall(#';
    }

    var hasNamed = argumentList.arguments.any((a) => a is NamedExpression);
    if (hasNamed) {
      jsCode += ', [#], #)';
      jsArgs.add(args.take(args.length - 1));
      jsArgs.add(args.last);
    } else {
      jsArgs.add(args);
      jsCode += ', [#])';
    }

    return runtimeCall(jsCode, jsArgs);
  }

  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 !jsTypeRep.equalityMayConvert(left.staticType, right.staticType);
  }

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

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

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

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

  /// Emits a function call, to a top-level function, local function, or
  /// an expression.
  JS.Node _emitFunctionCall(InvocationExpression node, [Expression function]) {
    function ??= node.function;
    var castTo = getImplicitOperationCast(function);
    if (castTo != null) {
      function = CoercionReifier.castExpression(function, castTo);
    }
    if (function is Identifier) {
      var element = function.staticElement;
      if (element == _coreIdentical) {
        return _emitCoreIdenticalCall(node.argumentList.arguments);
      }
      var uri = element.librarySource.uri;
      if (uri.scheme == 'dart' &&
          uri.path.startsWith('developer') &&
          element.name == 'debugger') {
        return _emitDebuggerCall(node);
      }
    }

    var args = _emitArgumentList(node.argumentList);
    var typeArgs = _emitInvokeTypeArguments(node);
    var fn = _visitExpression(function);
    if (isDynamicInvoke(function)) {
      return _emitDynamicInvoke(fn, typeArgs, null, args, node.argumentList);
    }
    if (typeArgs != null) args.insertAll(0, typeArgs);

    var targetType = function.staticType;
    if (targetType is InterfaceType) {
      var callName = _getImplicitCallTarget(targetType);
      if (callName != null) {
        return js.call('#.#(#)', [fn, callName, args]);
      }
    }

    return JS.Call(fn, args);
  }

  JS.Node _emitDebuggerCall(InvocationExpression node) {
    var args = node.argumentList.arguments;
    var isStatement = node.parent is ExpressionStatement;
    if (args.isEmpty) {
      // Inline `debugger()` with no arguments, as a statement if possible,
      // otherwise as an immediately invoked function.
      return isStatement
          ? js.statement('debugger;')
          : js.call('(() => { debugger; return true})()');
    }

    // 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 = <JS.Property>[];
    var foundWhen = false;
    for (var arg in args) {
      var namedArg = arg as NamedExpression;
      if (namedArg.name.label.name == 'when') foundWhen = true;
      jsArgs.add(visitNamedExpression(namedArg));
    }
    var when = jsArgs.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`).
        ? (foundWhen ? jsArgs[0].value : JS.ObjectInitializer(jsArgs))
        // If we have both `message` and `when` arguments, evaluate them in
        // order, then extract the `when` argument.
        : js.call('#.when', JS.ObjectInitializer(jsArgs));
    return isStatement
        ? js.statement('if (#) debugger;', when)
        : js.call('# && (() => { debugger; return true })()', when);
  }

  List<JS.Expression> _emitInvokeTypeArguments(InvocationExpression node) {
    // add no reify generic check here: if (node.function)
    // node is Identifier
    var function = node.function;
    if (function is Identifier && !_reifyGeneric(function.staticElement)) {
      return null;
    }
    return _emitFunctionTypeArguments(
        function.staticType, node.staticInvokeType, node.typeArguments);
  }

  /// If `g` is a generic function type, and `f` is an instantiation of it,
  /// then this will return the type arguments to apply, otherwise null.
  List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f,
      [TypeArgumentList typeArgs]) {
    if (g is FunctionType &&
        g.typeFormals.isNotEmpty &&
        f is FunctionType &&
        f.typeFormals.isEmpty) {
      return _recoverTypeArguments(g, f).map(_emitType).toList(growable: false);
    } else if (typeArgs != null) {
      // Dynamic calls may have type arguments, even though the function types
      // are not known.
      return _visitExpressionList(typeArgs.arguments);
    }
    return null;
  }

  /// Given a generic function type [g] and an instantiated function type [f],
  /// find a list of type arguments TArgs such that `g<TArgs> == f`,
  /// and return TArgs.
  ///
  /// This function must be called with type [f] that was instantiated from [g].
  Iterable<DartType> _recoverTypeArguments(FunctionType g, FunctionType f) {
    // TODO(jmesserly): this design is a bit unfortunate. It would be nice if
    // resolution could simply create a synthetic type argument list.
    assert(g.typeFormals.isNotEmpty && f.typeFormals.isEmpty);
    assert(g.typeFormals.length <= f.typeArguments.length);

    // Instantiation in Analyzer works like this:
    // Given:
    //     {U/T} <S> T -> S
    // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
    // and <S> represents the typeFormals.
    //
    // Now instantiate([V]), and the result should be:
    //     {U/T, V/S} T -> S.
    //
    // Therefore, we can recover the typeArguments from our instantiated
    // function.
    return f.typeArguments.skip(f.typeArguments.length - g.typeFormals.length);
  }

  /// Emits code for the `JS(...)` macro.
  JS.Node _emitForeignJS(MethodInvocation node, Element e) {
    if (!isInlineJS(e)) return null;

    var args = node.argumentList.arguments;
    // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
    var code = args[1];
    List<Expression> templateArgs;
    String source;
    if (code is StringInterpolation) {
      if (args.length > 2) {
        throw ArgumentError(
            "Can't mix template args and string interpolation in JS calls.");
      }
      templateArgs = <Expression>[];
      source = code.elements.map((element) {
        if (element is InterpolationExpression) {
          templateArgs.add(element.expression);
          return '#';
        } else {
          return (element as InterpolationString).value;
        }
      }).join();
    } else {
      templateArgs = args.skip(2).toList();
      source = (code as StringLiteral).stringValue;
    }

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

    // `throw` is emitted as a statement by `parseForeignJS`.
    assert(result is JS.Expression ||
        result is JS.Statement && node.parent is ExpressionStatement);
    return result;
  }

  @override
  JS.Node visitFunctionExpressionInvocation(
          FunctionExpressionInvocation node) =>
      _emitFunctionCall(node);

  List<JS.Expression> _emitArgumentList(ArgumentList node) {
    var args = <JS.Expression>[];
    var named = <JS.Property>[];
    for (var arg in node.arguments) {
      if (arg is NamedExpression) {
        named.add(visitNamedExpression(arg));
      } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) {
        args.add(JS.Spread(_visitExpression(arg.argumentList.arguments[0])));
      } else {
        args.add(_visitExpression(arg));
      }
    }
    if (named.isNotEmpty) {
      args.add(JS.ObjectInitializer(named));
    }
    return args;
  }

  @override
  JS.Property visitNamedExpression(NamedExpression node) {
    assert(node.parent is ArgumentList);
    return JS.Property(
        _propertyName(node.name.label.name), _visitExpression(node.expression));
  }

  List<JS.Parameter> _emitParametersForElement(ExecutableElement member) {
    var jsParams = <JS.Identifier>[];
    for (var p in member.parameters) {
      if (p.isPositional) {
        jsParams.add(JS.Identifier(p.name));
      } else {
        jsParams.add(namedArgumentTemp);
        break;
      }
    }
    return jsParams;
  }

  List<JS.Parameter> _emitParameters(Iterable<FormalParameter> parameters) {
    if (parameters == null) return [];

    var result = <JS.Parameter>[];
    for (var param in parameters) {
      if (param.isNamed) {
        result.add(namedArgumentTemp);
        break;
      }
      result.add(_emitFormalParameter(param));
    }

    return result;
  }

  @override
  JS.Statement visitExpressionStatement(ExpressionStatement node) =>
      node.expression.accept(this).toStatement();

  @override
  JS.EmptyStatement visitEmptyStatement(EmptyStatement node) =>
      JS.EmptyStatement();

  @override
  JS.Statement visitAssertStatement(AssertStatement node) =>
      _emitAssert(node.condition, node.message);

  JS.Statement _emitAssert(Expression condition, Expression message) {
    if (!options.enableAsserts) return JS.EmptyStatement();
    // TODO(jmesserly): only emit in checked mode.
    var conditionType = condition.staticType;
    var jsCondition = _visitExpression(condition);

    if (conditionType is FunctionType &&
        conditionType.parameters.isEmpty &&
        conditionType.returnType == types.boolType) {
      jsCondition = runtimeCall('test(#())', jsCondition);
    } else if (conditionType != types.boolType) {
      jsCondition = runtimeCall('dassert(#)', jsCondition);
    } else if (isNullable(condition)) {
      jsCondition = runtimeCall('test(#)', jsCondition);
    }
    return js.statement(' if (!#) #.assertFailed(#);', [
      jsCondition,
      runtimeModule,
      message != null ? [_visitExpression(message)] : []
    ]);
  }

  @override
  JS.Statement visitReturnStatement(ReturnStatement node) {
    return super.emitReturnStatement(_visitExpression(node.expression));
  }

  @override
  JS.Statement visitYieldStatement(YieldStatement node) {
    var jsExpr = _visitExpression(node.expression);
    var star = node.star != null;
    if (_asyncStarController != null) {
      // async* yields are generated differently from sync* yields. `yield e`
      // becomes:
      //
      //     if (stream.add(e)) return;
      //     yield;
      //
      // `yield* e` becomes:
      //
      //     if (stream.addStream(e)) return;
      //     yield;
      var helperName = star ? 'addStream' : 'add';
      return js.statement('{ if(#.#(#)) return; #; }', [
        _asyncStarController,
        helperName,
        jsExpr,
        JS.Yield(null)..sourceInformation = _nodeStart(node)
      ]);
    }
    // A normal yield in a sync*
    return jsExpr.toYieldStatement(star: star);
  }

  @override
  JS.Expression visitAwaitExpression(AwaitExpression node) {
    return JS.Yield(_visitExpression(node.expression));
  }

  /// This is not used--we emit top-level fields as we are emitting the
  /// compilation unit, see [visitCompilationUnit].
  @override
  visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    return _unreachable(node);
  }

  /// This is not used--we emit fields as we are emitting the class,
  /// see [visitClassDeclaration].
  @override
  visitFieldDeclaration(FieldDeclaration node) {
    return _unreachable(node);
  }

  @override
  JS.Statement visitVariableDeclarationStatement(
      VariableDeclarationStatement node) {
    // Special case a single variable with an initializer.
    // This helps emit cleaner code for things like:
    //     var result = []..add(1)..add(2);
    var variables = node.variables.variables;
    if (variables.length == 1) {
      var variable = variables[0];
      var initializer = variable.initializer;
      if (initializer != null) {
        var name = _emitVariableDef(variable.name);
        JS.Expression value;
        if (_annotatedNullCheck(variable.declaredElement)) {
          value = notNull(initializer);
        } else if (initializer is FunctionExpression) {
          // This improve stack traces for the pattern:
          //
          //     var f = (y) => y.doesNotExist();
          //
          // ... by moving the type tagging after of the variable declaration:
          //
          //     let f = (y) => y.doesNotExist();
          //     dart.fn(f, typeOfF);
          //
          value = _emitArrowFunction(initializer);
          return JS.Block([
            value.toVariableDeclaration(name),
            _emitFunctionTagged(
                    name, getStaticType(initializer) as FunctionType,
                    topLevel: _executesAtTopLevel(node))
                .toStatement()
          ]);
        } else {
          value = _visitExpression(initializer);
        }
        return value.toVariableDeclaration(name);
      }
    }
    return visitVariableDeclarationList(node.variables).toStatement();
  }

  @override
  JS.VariableDeclarationList visitVariableDeclarationList(
      VariableDeclarationList node) {
    if (node == null) return null;
    return JS.VariableDeclarationList(
        'let', node.variables?.map(visitVariableDeclaration)?.toList());
  }

  @override
  JS.VariableInitialization visitVariableDeclaration(VariableDeclaration node) {
    if (node.declaredElement is PropertyInducingElement) {
      // All fields are handled elsewhere.
      assert(false);
      return null;
    }

    var name = _emitVariableDef(node.name);
    return JS.VariableInitialization(
        name, _visitInitializer(node.initializer, node.declaredElement));
  }

  /// Emits a list of top-level field.
  void _emitTopLevelFields(List<VariableDeclaration> fields) {
    moduleItems.add(_emitLazyFields(
        emitLibraryName(currentLibrary), fields, _emitTopLevelMemberName));
  }

  /// Treat dart:_runtime fields as safe to eagerly evaluate.
  // TODO(jmesserly): it'd be nice to avoid this special case.
  List<VariableDeclaration> _emitInternalSdkFields(
      List<VariableDeclaration> fields) {
    var lazyFields = <VariableDeclaration>[];
    for (var field in fields) {
      // Skip our magic undefined constant.
      var element = field.declaredElement as TopLevelVariableElement;
      if (element.name == 'undefined') continue;

      var init = field.initializer;
      if (init == null ||
          init is Literal ||
          _isJSInvocation(init) ||
          init is InstanceCreationExpression &&
              isSdkInternalRuntime(init.staticElement.library)) {
        moduleItems.add(js.statement('# = #;', [
          _emitTopLevelName(field.declaredElement),
          _visitInitializer(field.initializer, field.declaredElement)
        ]));
      } else {
        lazyFields.add(field);
      }
    }
    return lazyFields;
  }

  JS.Expression _visitInitializer(Expression init, Element variable) {
    // 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.LiteralNull();
    return _annotatedNullCheck(variable)
        ? notNull(init)
        : _visitExpression(init);
  }

  JS.Statement _emitLazyFields(
      JS.Expression objExpr,
      List<VariableDeclaration> fields,
      JS.Expression Function(Element e) emitFieldName) {
    var accessors = <JS.Method>[];

    for (var node in fields) {
      var element = node.declaredElement;
      var access = emitFieldName(element);
      accessors.add(JS.Method(
          access,
          js.call('function() { return #; }',
              _visitInitializer(node.initializer, element)) as JS.Fun,
          isGetter: true)
        ..sourceInformation =
            _hoverComment(JS.PropertyAccess(objExpr, access), node.name));

      // TODO(jmesserly): currently uses a dummy setter to indicate writable.
      if (!node.isFinal && !node.isConst) {
        accessors.add(JS.Method(access, js.call('function(_) {}') as JS.Fun,
            isSetter: true));
      }
    }

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

  JS.Expression _emitConstructorName(DartType type, String name) {
    return _emitJSInterop(type.element) ??
        JS.PropertyAccess(_emitConstructorAccess(type), _constructorName(name));
  }

  @override
  JS.Expression visitConstructorName(ConstructorName node) {
    return _emitConstructorName(node.type.type, node.staticElement.name);
  }

  JS.Expression _emitInstanceCreationExpression(ConstructorElement element,
      InterfaceType type, List<JS.Expression> Function() emitArguments,
      {bool isConst = false, ConstructorName ctorNode}) {
    if (element == null) {
      return _throwUnsafe('unresolved constructor: ${type?.name ?? '<null>'}'
          '.${ctorNode?.name?.name ?? '<unnamed>'}');
    }

    var classElem = type.element;
    if (_isObjectLiteral(classElem)) {
      var args = emitArguments();
      return args.isEmpty ? js.call('{}') : args.single as JS.ObjectInitializer;
    }

    var name = element.name;
    JS.Expression emitNew() {
      var args = emitArguments();
      if (args.isEmpty && classElem.source.isInSystemLibrary) {
        // Skip the slow SDK factory constructors when possible.
        switch (classElem.name) {
          case 'Map':
          case 'HashMap':
          case 'LinkedHashMap':
            if (name == '') {
              return js.call('new #.new()', _emitMapImplType(type));
            } else if (name == 'identity') {
              return js.call(
                  'new #.new()', _emitMapImplType(type, identity: true));
            }
            break;
          case 'Set':
          case 'HashSet':
          case 'LinkedHashSet':
            if (name == '') {
              return js.call('new #.new()', _emitSetImplType(type));
            } else if (name == 'identity') {
              return js.call(
                  'new #.new()', _emitSetImplType(type, identity: true));
            }
            break;
          case 'List':
            if (name == '' && type is InterfaceType) {
              return _emitList(type.typeArguments[0], []);
            }
            break;
        }
      }
      // Native factory constructors are JS constructors - use new here.
      var ctor = _emitConstructorName(type, name);
      if (ctorNode != null) ctor.sourceInformation = _nodeSpan(ctorNode);
      return element.isFactory && !_hasJSInteropAnnotation(classElem)
          ? JS.Call(ctor, args)
          : JS.New(ctor, args);
    }

    return isConst ? _emitConst(emitNew) : emitNew();
  }

  bool _isObjectLiteral(Element classElem) {
    return _hasJSInteropAnnotation(classElem) &&
        findAnnotation(classElem, isJSAnonymousAnnotation) != null;
  }

  /// Returns true iff the class has an `@JS(...)` annotation from `package:js`.
  ///
  /// Note: usually [_usesJSInterop] should be used instead of this.
  //
  // TODO(jmesserly): I think almost all uses of this should be replaced with
  // [_usesJSInterop], which also checks that the library is marked with `@JS`.
  //
  // Right now we have inconsistencies: sometimes we'll respect `@JS` on the
  // class itself, other places we require it on the library. Also members are
  // inconsistent: sometimes they need to have `@JS` on them, other times they
  // need to be `external` in an `@JS` class.
  bool _hasJSInteropAnnotation(Element e) =>
      findAnnotation(e, isPublicJSAnnotation) != null;

  /// If the constant [value] is primitive, directly emit the
  /// corresponding JavaScript.  Otherwise, return null.
  JS.Expression _emitDartObject(DartObject value,
      {bool handleUnknown = false}) {
    if (value == null || value.isNull) {
      return JS.LiteralNull();
    }
    var type = value.type;
    // Handle unknown value: when the declared variable wasn't found, and no
    // explicit default value was passed either.
    // TODO(jmesserly): ideally Analyzer would simply resolve this to the
    // default value that is specified in the SDK. Instead we implement that
    // here. `bool.fromEnvironment` defaults to `false`, the others to `null`:
    // https://api.dartlang.org/stable/1.20.1/dart-core/bool/bool.fromEnvironment.html
    if (!value.hasKnownValue) {
      if (!handleUnknown) return null;
      return type == types.boolType ? js.boolean(false) : JS.LiteralNull();
    }
    if (type == types.boolType) {
      return js.boolean(value.toBoolValue());
    }
    if (type == types.intType) {
      return js.number(value.toIntValue());
    }
    if (type == types.doubleType) {
      return js.number(value.toDoubleValue());
    }
    if (type == types.stringType) {
      var stringValue = value.toStringValue();
      return js.escapedString(stringValue);
    }
    if (type == types.symbolType) {
      return _emitDartSymbol(value.toSymbolValue());
    }
    if (type == types.typeType) {
      return _emitType(value.toTypeValue());
    }
    if (type is InterfaceType) {
      if (type.element == types.listType.element) {
        return _cacheConst(() => _emitConstList(type.typeArguments[0],
            value.toListValue().map(_emitDartObject).toList()));
      }
      if (type.element == types.mapType.element) {
        return _cacheConst(() {
          var entries = <JS.Expression>[];
          value.toMapValue().forEach((key, value) {
            entries.add(_emitDartObject(key));
            entries.add(_emitDartObject(value));
          });
          return _emitConstMap(type, entries);
        });
      }
      if (value is DartObjectImpl && value.isUserDefinedObject) {
        var ctor = value.getInvocation();
        var classElem = type.element;
        if (classElem.isEnum) {
          // TODO(jmesserly): we should be able to use `getField('index')` but
          // in some cases Analyzer uses the name of the static field that
          // contains the enum, rather than the `index` field, due to a bug.
          //
          // So we just grab the one instance field, regardless of its name.
          var index = value.fields.values.single.toIntValue();
          var field =
              classElem.fields.where((f) => f.type == type).elementAt(index);
          return _emitClassMemberElement(field, field.getter, null);
        }
        return _emitInstanceCreationExpression(ctor.constructor, type, () {
          var args = ctor.positionalArguments.map(_emitDartObject).toList();
          var named = <JS.Property>[];
          ctor.namedArguments.forEach((name, value) {
            named.add(JS.Property(_propertyName(name), _emitDartObject(value)));
          });
          if (named.isNotEmpty) args.add(JS.ObjectInitializer(named));
          return args;
        }, isConst: true);
      }
    }
    if (value is DartObjectImpl && type is FunctionType) {
      Element element = value.toFunctionValue();
      if (element.enclosingElement is CompilationUnitElement) {
        return _emitLibraryMemberElement(element, null);
      }
      if (element is ClassMemberElement) {
        return _emitClassMemberElement(element, element, null);
      }
    }
    return _unreachable(value);
  }

  @override
  visitInstanceCreationExpression(InstanceCreationExpression node) {
    var element = resolutionMap.staticElementForConstructorReference(node);
    var constructor = node.constructorName;
    if (node.isConst &&
        element?.name == 'fromEnvironment' &&
        element.library.isDartCore) {
      var value = node.accept(_constants.constantVisitor);

      var result = _emitDartObject(value, handleUnknown: true);
      if (result != null) {
        return result;
      }
      throw StateError('failed to evaluate $node');
    }

    // TODO(jmesserly): this is a workaround for Analyzer's type not
    // correctly tracking typedefs used in type arguments.
    DartType getType(TypeAnnotation typeNode) {
      if (typeNode is NamedType && typeNode.typeArguments != null) {
        var e = typeNode.name.staticElement;
        if (e is TypeParameterizedElement) {
          return e.type.instantiate(
              typeNode.typeArguments.arguments.map(getType).toList());
        }
      }
      return typeNode.type;
    }

    return _emitInstanceCreationExpression(
        element,
        getType(constructor.type) as InterfaceType,
        () => _emitArgumentList(node.argumentList),
        isConst: node.isConst,
        ctorNode: constructor);
  }

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

  JS.Expression notNull(Expression expr) {
    if (expr == null) return null;
    var jsExpr = _visitExpression(expr);
    if (!isNullable(expr)) return jsExpr;
    return runtimeCall('notNull(#)', jsExpr);
  }

  JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
    var left = node.leftOperand;
    var right = node.rightOperand;
    var leftType = left.staticType;
    var negated = op.type == TokenType.BANG_EQ;

    if (left is SuperExpression) {
      return _emitOperatorCall(left, op.lexeme, [right], node.staticElement);
    }

    // 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.
    var isEnum = leftType is InterfaceType && leftType.element.isEnum;
    var usesIdentity = jsTypeRep.isPrimitive(leftType) ||
        isEnum ||
        _isNull(left) ||
        _isNull(right);

    // If we know that the left type uses identity for equality, we can
    // sometimes emit better code, either `===` or `==`.
    if (usesIdentity) {
      return _emitCoreIdenticalCall([left, right], negated: negated);
    }

    // If the left side is nullable, we need to use a runtime helper to check
    // for null. We could inline the null check, but it did not seem to have
    // a measurable performance effect (possibly the helper is simple enough to
    // be inlined).
    if (isNullable(left)) {
      var code = negated ? '!#.equals(#, #)' : '#.equals(#, #)';
      return js.call(code,
          [runtimeModule, _visitExpression(left), _visitExpression(right)]);
    }

    // Otherwise we emit a call to the == method.
    var name = _emitMemberName('==', type: leftType);
    var code = negated ? '!#[#](#)' : '#[#](#)';
    return js
        .call(code, [_visitExpression(left), name, _visitExpression(right)]);
  }

  @override
  JS.Expression visitBinaryExpression(BinaryExpression node) {
    var op = node.operator;

    // The operands of logical boolean operators are subject to boolean
    // conversion.
    if (op.type == TokenType.BAR_BAR ||
        op.type == TokenType.AMPERSAND_AMPERSAND) {
      return _visitTest(node)
        ..sourceInformation = _getLocation(node.operator.offset);
    }

    if (op.type.isEqualityOperator) return _emitEqualityOperator(node, op);

    var left = node.leftOperand;
    var right = node.rightOperand;

    if (op.type.lexeme == '??') {
      // TODO(jmesserly): leave RHS for debugging?
      // This should be a hint or warning for dead code.
      if (!isNullable(left)) return _visitExpression(left);

      var vars = <JS.MetaLetVariable, JS.Expression>{};
      // Desugar `l ?? r` as `l != null ? l : r`
      var l = _visitExpression(_bindValue(vars, 'l', left, context: left));
      return JS.MetaLet(vars, [
        js.call('# != null ? # : #', [l, l, _visitExpression(right)])
      ]);
    }

    var leftType = getStaticType(left);
    var rightType = getStaticType(right);

    JS.Expression operatorCall() {
      return _emitOperatorCall(left, op.lexeme, [right])
        ..sourceInformation = _getLocation(node.operator.offset);
    }

    if (jsTypeRep.binaryOperationIsPrimitive(leftType, rightType) ||
        leftType == types.stringType && op.type == TokenType.PLUS) {
      // 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.Expression binary(String code) {
        return js.call(code, [notNull(left), notNull(right)])
          ..sourceInformation = _getLocation(node.operator.offset);
      }

      JS.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.Expression bitwiseBool(String code) {
        return js.call(code, [notNull(left), _visitTest(right)])
          ..sourceInformation = _getLocation(node.operator.offset);
      }

      switch (op.type) {
        case TokenType.TILDE_SLASH:
          // `a ~/ b` is equivalent to `(a / b).truncate()`
          var div = ast.binaryExpression(left, '/', right)
            ..staticType = node.staticType;
          return _emitOperatorCall(div, 'truncate', [])
            ..sourceInformation = _getLocation(node.operator.offset);

        case TokenType.PERCENT:
          // TODO(sra): We can generate `a % b + 0` if both are non-negative
          // (the `+ 0` is to coerce -0.0 to 0).
          return operatorCall();

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

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

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

        case TokenType.GT_GT:
          int 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 operatorCall();

        case TokenType.LT_LT:
          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 operatorCall();

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

    return operatorCall();
  }

  /// 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.Expression _coerceBitOperationResultToUnsigned(
      Expression node, JS.Expression uncoerced) {
    // Don't coerce if the parent will coerce.
    AstNode parent = _parentOperation(node);
    if (_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`.
    if (parent is BinaryExpression) {
      var tokenType = parent.operator.type;
      Expression left = parent.leftOperand;
      Expression right = parent.rightOperand;
      if (tokenType == TokenType.EQ_EQ || tokenType == TokenType.BANG_EQ) {
        const int MAX = 0x7fffffff;
        if (_asIntInRange(right, 0, MAX) != null) return uncoerced;
        if (_asIntInRange(left, 0, MAX) != null) return uncoerced;
      } else if (tokenType == TokenType.GT_GT) {
        if (_isDefinitelyNonNegative(left) &&
            _asIntInRange(right, 0, 31) != null) {
          // Parent will generate `# >>> n`.
          return uncoerced;
        }
      }
    }
    return js.call('# >>> 0', uncoerced);
  }

  AstNode _parentOperation(AstNode node) {
    node = node.parent;
    while (node is ParenthesizedExpression) node = node.parent;
    return node;
  }

  bool _nodeIsBitwiseOperation(AstNode node) {
    if (node is BinaryExpression) {
      switch (node.operator.type) {
        case TokenType.AMPERSAND:
        case TokenType.BAR:
        case TokenType.CARET:
          return true;
      }
      return false;
    }
    if (node is PrefixExpression) {
      return node.operator.type == TokenType.TILDE;
    }
    return false;
  }

  int _asIntInRange(Expression expr, int low, int high) {
    expr = expr.unParenthesized;
    if (expr is IntegerLiteral) {
      var value = getLiteralBigIntValue(expr);
      if (value != null &&
          value >= BigInt.from(low) &&
          value <= BigInt.from(high)) {
        return expr.value;
      }
      return null;
    }

    Identifier id;
    if (expr is SimpleIdentifier) {
      id = expr;
    } else if (expr is PrefixedIdentifier && !expr.isDeferred) {
      id = expr.identifier;
    } else {
      return null;
    }
    var element = id.staticElement;
    if (element is PropertyAccessorElement && element.isGetter) {
      var variable = element.variable;
      int value = variable?.computeConstantValue()?.toIntValue();
      if (value != null && value >= low && value <= high) return value;
    }
    return null;
  }

  bool _isDefinitelyNonNegative(Expression expr) {
    expr = expr.unParenthesized;
    if (expr is IntegerLiteral) {
      var value = getLiteralBigIntValue(expr);
      return value != null && value >= BigInt.from(0);
    }
    if (_nodeIsBitwiseOperation(expr)) return true;
    // TODO(sra): Lengths of known list types etc.
    return false;
  }

  /// Does the parent of [node] mask the result to [width] bits or fewer?
  bool _parentMasksToWidth(AstNode node, int width) {
    AstNode parent = _parentOperation(node);
    if (parent == null) return false;
    if (_nodeIsBitwiseOperation(parent)) {
      if (parent is BinaryExpression &&
          parent.operator.type == TokenType.AMPERSAND) {
        Expression left = parent.leftOperand;
        Expression right = parent.rightOperand;
        final int MAX = (1 << width) - 1;
        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 int 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 IntegerLiteral && expr.value != null) {
        return expr.value >= 0 ? expr.value.bitLength : MAX;
      }
      if (++depth > 5) return MAX;
      if (expr is BinaryExpression) {
        var left = expr.leftOperand.unParenthesized;
        var right = expr.rightOperand.unParenthesized;
        switch (expr.operator.type) {
          case TokenType.AMPERSAND:
            return min(bitWidth(left, depth), bitWidth(right, depth));

          case TokenType.BAR:
          case TokenType.CARET:
            return max(bitWidth(left, depth), bitWidth(right, depth));

          case TokenType.GT_GT:
            int shiftValue = _asIntInRange(right, 0, 31);
            if (shiftValue != null) {
              int leftWidth = bitWidth(left, depth);
              return leftWidth == MAX ? MAX : max(0, leftWidth - shiftValue);
            }
            return MAX;

          case TokenType.LT_LT:
            int leftWidth = bitWidth(left, depth);
            int shiftValue = _asIntInRange(right, 0, 31);
            if (shiftValue != null) {
              return min(MAX, leftWidth + shiftValue);
            }
            int 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;
        }
      }
      int value = _asIntInRange(expr, 0, 0x7fffffff);
      if (value != null) return value.bitLength;
      return MAX;
    }

    return bitWidth(expr, 0) < 32;
  }

  bool _isNull(Expression expr) =>
      expr is NullLiteral || getStaticType(expr).isDartCoreNull;

  SimpleIdentifier _createTemporary(String name, DartType type,
      {bool nullable = true, JS.Expression variable, bool dynamicInvoke}) {
    // We use an invalid source location to signal that this is a temporary.
    // See [_isTemporary].
    // TODO(jmesserly): alternatives are
    // * (ab)use Element.isSynthetic, which isn't currently used for
    //   LocalVariableElementImpl, so we could repurpose to mean "temp".
    // * add a new property to LocalVariableElementImpl.
    // * create a new subtype of LocalVariableElementImpl to mark a temp.
    var id = astFactory
        .simpleIdentifier(StringToken(TokenType.IDENTIFIER, name, -1));

    variable ??= JS.TemporaryId(name);

    var idElement = TemporaryVariableElement.forNode(id, variable)
      ..enclosingElement = _currentElement;
    id.staticElement = idElement;
    id.staticType = type;
    setIsDynamicInvoke(id, dynamicInvoke ?? type.isDynamic);
    addTemporaryVariable(idElement, nullable: nullable);
    return id;
  }

  JS.Expression _cacheConst(JS.Expression expr()) {
    var savedTypeParams = _typeParamInConst;
    _typeParamInConst = [];

    var jsExpr = expr();

    bool usesTypeParams = _typeParamInConst.isNotEmpty;
    _typeParamInConst = savedTypeParams;

    // TODO(jmesserly): if it uses type params we can still hoist it up as far
    // as it will go, e.g. at the level the generic class is defined where type
    // params are available.
    if (_currentFunction == null || usesTypeParams) return jsExpr;

    var temp = JS.TemporaryId('const');
    moduleItems.add(js.statement('let #;', [temp]));
    return js.call('# || (# = #)', [temp, temp, jsExpr]);
  }

  JS.Expression _emitConst(JS.Expression expr()) =>
      _cacheConst(() => runtimeCall('const(#)', expr()));

  /// Returns a new expression, which can be be used safely *once* on the
  /// left hand side, and *once* on the right side of an assignment.
  /// For example: `expr1[expr2] += y` can be compiled as
  /// `expr1[expr2] = expr1[expr2] + y`.
  ///
  /// The temporary scope will ensure `expr1` and `expr2` are only evaluated
  /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`.
  ///
  /// If the expression does not end up using `x1` or `x2` more than once, or
  /// if those expressions can be treated as stateless (e.g. they are
  /// non-mutated variables), then the resulting code will be simplified
  /// automatically.
  ///
  /// [scope] can be mutated to contain any new temporaries that were created,
  /// unless [expr] is a SimpleIdentifier, in which case a temporary is not
  /// needed.
  Expression _bindLeftHandSide(
      Map<JS.MetaLetVariable, JS.Expression> scope, Expression expr,
      {Expression context}) {
    Expression result;
    if (expr is IndexExpression) {
      IndexExpression index = expr;
      result = astFactory.indexExpressionForTarget(
          _bindValue(scope, 'o', index.target, context: context),
          index.leftBracket,
          _bindValue(scope, 'i', index.index, context: context),
          index.rightBracket);
    } else if (expr is PropertyAccess) {
      PropertyAccess prop = expr;
      result = astFactory.propertyAccess(
          _bindValue(scope, 'o', _getTarget(prop), context: context),
          prop.operator,
          prop.propertyName);
    } else if (expr is PrefixedIdentifier) {
      PrefixedIdentifier ident = expr;
      if (isLibraryPrefix(ident.prefix)) {
        return expr;
      }
      result = astFactory.prefixedIdentifier(
          _bindValue(scope, 'o', ident.prefix, context: context)
              as SimpleIdentifier,
          ident.period,
          ident.identifier);
    } else {
      return expr as SimpleIdentifier;
    }
    result.staticType = expr.staticType;
    setIsDynamicInvoke(result, isDynamicInvoke(expr));
    return result;
  }

  /// Creates a temporary to contain the value of [expr]. The temporary can be
  /// used multiple times in the resulting expression. For example:
  /// `expr ** 2` could be compiled as `expr * expr`. The temporary scope will
  /// ensure `expr` is only evaluated once: `(x => x * x)(expr)`.
  ///
  /// If the expression does not end up using `x` more than once, or if those
  /// expressions can be treated as stateless (e.g. they are non-mutated
  /// variables), then the resulting code will be simplified automatically.
  ///
  /// [scope] will be mutated to contain the new temporary's initialization.
  Expression _bindValue(Map<JS.MetaLetVariable, JS.Expression> scope,
      String name, Expression expr,
      {Expression context}) {
    // No need to do anything for stateless expressions.
    if (isStateless(_currentFunction, expr, context)) return expr;

    var variable = JS.MetaLetVariable(name);
    var t = _createTemporary(name, getStaticType(expr),
        variable: variable,
        dynamicInvoke: isDynamicInvoke(expr),
        nullable: isNullable(expr));
    scope[variable] = _visitExpression(expr);
    return t;
  }

  /// Desugars postfix increment.
  ///
  /// In the general case [expr] can be one of [IndexExpression],
  /// [PrefixExpression] or [PropertyAccess] and we need to
  /// ensure sub-expressions are evaluated once.
  ///
  /// We also need to ensure we can return the original value of the expression,
  /// and that it is only evaluated once.
  ///
  /// We desugar this using let*.
  ///
  /// For example, `expr1[expr2]++` can be transformed to this:
  ///
  ///     // pseudocode mix of Scheme and JS:
  ///     (let* (x1=expr1, x2=expr2, t=expr1[expr2]) { x1[x2] = t + 1; t })
  ///
  /// The [JS.MetaLet] nodes automatically simplify themselves if they can.
  /// For example, if the result value is not used, then `t` goes away.
  @override
  JS.Expression visitPostfixExpression(PostfixExpression node) {
    var op = node.operator;
    var expr = node.operand;

    var dispatchType = getStaticType(expr);
    if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
      if (!isNullable(expr)) {
        return js.call('#$op', _visitExpression(expr));
      }
    }

    assert(op.lexeme == '++' || op.lexeme == '--');

    // Handle the left hand side, to ensure each of its subexpressions are
    // evaluated only once.
    var vars = <JS.MetaLetVariable, JS.Expression>{};
    var left = _bindLeftHandSide(vars, expr, context: expr);

    // Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value
    // and `x1` is the new value for `x`.
    var x = _bindValue(vars, 'x', left, context: expr);

    var one = ast.integerLiteral(1)..staticType = types.intType;
    var increment = ast.binaryExpression(x, op.lexeme[0], one)
      ..staticElement = node.staticElement
      ..staticType = getStaticType(expr);

    var body = <JS.Expression>[_emitSet(left, increment), _visitExpression(x)];
    return JS.MetaLet(vars, body, statelessResult: true);
  }

  @override
  JS.Expression visitPrefixExpression(PrefixExpression node) {
    var op = node.operator;

    // Logical negation, `!e`, is a boolean conversion context since it is
    // defined as `e ? false : true`.
    if (op.lexeme == '!') return _visitTest(node);

    var expr = node.operand;

    var dispatchType = getStaticType(expr);
    if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
      if (op.lexeme == '~') {
        if (jsTypeRep.isNumber(dispatchType)) {
          JS.Expression jsExpr = js.call('~#', notNull(expr));
          return _coerceBitOperationResultToUnsigned(node, jsExpr);
        }
        return _emitOperatorCall(expr, op.lexeme[0], []);
      }
      if (!isNullable(expr)) {
        return js.call('$op#', _visitExpression(expr));
      }
      if (op.lexeme == '++' || op.lexeme == '--') {
        // We need a null check, so the increment must be expanded out.
        var vars = <JS.MetaLetVariable, JS.Expression>{};
        var x = _bindLeftHandSide(vars, expr, context: expr);

        var one = ast.integerLiteral(1)..staticType = types.intType;
        var increment = ast.binaryExpression(x, op.lexeme[0], one)
          ..staticElement = node.staticElement
          ..staticType = getStaticType(expr);

        return JS.MetaLet(vars, [_emitSet(x, increment)]);
      }
      return js.call('$op#', notNull(expr));
    }

    if (op.lexeme == '++' || op.lexeme == '--') {
      // Increment or decrement requires expansion.
      // Desugar `++x` as `x = x + 1`, ensuring that if `x` has subexpressions
      // (for example, x is IndexExpression) we evaluate those once.
      var one = ast.integerLiteral(1)..staticType = types.intType;
      return _emitOpAssign(expr, one, op.lexeme[0], node.staticElement,
          context: expr);
    }

    var operatorName = op.lexeme;
    // Use the name from the Dart spec.
    if (operatorName == '-') operatorName = 'unary-';
    return _emitOperatorCall(expr, operatorName, []);
  }

  // Cascades can contain [IndexExpression], [MethodInvocation] and
  // [PropertyAccess]. The code generation for those is handled in their
  // respective visit methods.
  @override
  visitCascadeExpression(CascadeExpression node) {
    var savedCascadeTemp = _cascadeTarget;

    var vars = <JS.MetaLetVariable, JS.Expression>{};
    _cascadeTarget = _bindValue(vars, '_', node.target, context: node);
    var sections = _visitExpressionList(node.cascadeSections);
    sections.add(_visitExpression(_cascadeTarget));
    var result = JS.MetaLet(vars, sections, statelessResult: true);
    _cascadeTarget = savedCascadeTemp;
    return result;
  }

  @override
  JS.Expression visitParenthesizedExpression(ParenthesizedExpression node) =>
      // The printer handles precedence so we don't need to.
      _visitExpression(node.expression);

  JS.Parameter _emitFormalParameter(FormalParameter node) {
    var id = _emitParameter(node.declaredElement, declaration: true)
      ..sourceInformation = _nodeSpan(node);
    var isRestArg = node is! DefaultFormalParameter &&
        findAnnotation(node.declaredElement, isJsRestAnnotation) != null;
    return isRestArg ? JS.RestParameter(id) : id;
  }

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

  @override
  JS.Expression visitSuperExpression(SuperExpression node) => JS.Super();

  @override
  visitPrefixedIdentifier(PrefixedIdentifier node) {
    if (_isDeferredLoadLibrary(node.prefix, node.identifier)) {
      // We are tearing off "loadLibrary" on a library prefix.
      return runtimeCall('loadLibrary');
    }

    if (isLibraryPrefix(node.prefix)) {
      return visitSimpleIdentifier(node.identifier, node);
    } else {
      return _emitPropertyGet(node.prefix, node.identifier, node);
    }
  }

  @override
  visitPropertyAccess(PropertyAccess node) {
    if (node.operator.lexeme == '?.' && isNullable(node.target)) {
      return _emitNullSafe(node);
    }
    return _emitPropertyGet(_getTarget(node), node.propertyName, node);
  }

  JS.Expression _emitNullSafe(Expression node) {
    // Desugar `obj?.name` as ((x) => x == null ? null : x.name)(obj)
    var target = _getTarget(node);
    var vars = <JS.MetaLetVariable, JS.Expression>{};
    var t = _bindValue(vars, 't', target, context: target);

    var desugared = _stripNullAwareOp(node, t);
    return JS.MetaLet(vars, [
      js.call('# == null ? null : #',
          [_visitExpression(t), _visitExpression(desugared)])
    ]);
  }

  // TODO(jmesserly): this is dropping source location.
  Expression _stripNullAwareOp(Expression node, Expression newTarget) {
    if (node is PropertyAccess) {
      return ast.propertyAccess(newTarget, node.propertyName);
    } else {
      var invoke = node as MethodInvocation;
      return ast.methodInvoke(newTarget, invoke.methodName,
          invoke.typeArguments, invoke.argumentList.arguments)
        ..staticInvokeType = invoke.staticInvokeType;
    }
  }

  List<JS.Expression> _getTypeArgs(Element member, DartType instantiated) {
    DartType type;
    if (member is ExecutableElement) {
      type = member.type;
    } else if (member is VariableElement) {
      type = member.type;
    }

    // TODO(jmesserly): handle explicitly passed type args.
    if (type == null) return null;
    return _emitFunctionTypeArguments(type, instantiated);
  }

  /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
  JS.Expression _emitPropertyGet(
      Expression receiver, SimpleIdentifier memberId, Expression accessNode) {
    var resultType = accessNode.staticType;
    var accessor = memberId.staticElement;
    var memberName = memberId.name;
    var receiverType = getStaticType(receiver);
    if (memberName == 'call' && _isDirectCallable(receiverType)) {
      // Tearoff of `call` on a function type is a no-op;
      return _visitExpression(receiver);
    }

    // If `member` is a getter/setter, get the corresponding
    var field = _getNonAccessorElement(accessor);
    bool isStatic = field is ClassMemberElement && field.isStatic;
    var jsName = _emitMemberName(memberName,
        type: receiverType, isStatic: isStatic, element: accessor);
    if (isDynamicInvoke(receiver)) {
      return runtimeCall(
          'dload$_replSuffix(#, #)', [_visitExpression(receiver), jsName]);
    }

    var jsTarget = _emitTarget(receiver, accessor, isStatic);
    var isSuper = jsTarget is JS.Super;
    if (isSuper &&
        accessor.isSynthetic &&
        field is FieldElementImpl &&
        !virtualFields.isVirtual(field)) {
      // If super.x is a sealed field, then x is an instance property since
      // subclasses cannot override x.
      jsTarget = JS.This()..sourceInformation = jsTarget.sourceInformation;
    }

    JS.Expression result;
    if (isObjectMember(memberName) && isNullable(receiver)) {
      if (_isObjectMethodTearoff(memberName)) {
        result = runtimeCall('bind(#, #)', [jsTarget, jsName]);
      } else {
        result = runtimeCall('#(#)', [memberName, jsTarget]);
      }
    } else if (accessor is MethodElement &&
        _reifyTearoff(accessor, accessNode)) {
      if (isStatic) {
        result = _emitFunctionTagged(
            _emitTargetAccess(jsTarget, jsName, accessor, memberId),
            accessor.type);
      } else if (isSuper) {
        result = runtimeCall('bind(this, #, #)',
            [jsName, _emitTargetAccess(jsTarget, jsName, accessor, memberId)]);
      } else {
        result = runtimeCall('bind(#, #)', [jsTarget, jsName]);
      }
    } else {
      result = _emitTargetAccess(jsTarget, jsName, accessor, memberId);
    }

    var typeArgs = _getTypeArgs(accessor, resultType);
    return typeArgs == null
        ? result
        : runtimeCall('gbind(#, #)', [result, typeArgs]);
  }

  bool _reifyTearoff(ExecutableElement element, Expression node) {
    return !inInvocationContext(node) &&
        !_usesJSInterop(element) &&
        !_isInForeignJS &&
        _reifyFunctionType(element);
  }

  bool _isDirectCallable(DartType t) =>
      t is FunctionType || t is InterfaceType && _usesJSInterop(t.element);

  JS.Expression _getImplicitCallTarget(InterfaceType fromType) {
    var callMethod = fromType.lookUpInheritedMethod('call');
    if (callMethod == null || _usesJSInterop(fromType.element)) return null;
    return _emitMemberName('call', type: fromType, element: callMethod);
  }

  /// 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.Expression _emitOperatorCall(
      Expression target, String name, List<Expression> args,
      [Element element]) {
    // TODO(jmesserly): calls that don't pass `element` are probably broken for
    // `super` calls from disallowed super locations.
    var type = getStaticType(target);
    var memberName = _emitMemberName(name, type: type);
    if (isDynamicInvoke(target)) {
      // dynamic dispatch
      var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
      if (dynamicHelper != null) {
        return runtimeCall('$dynamicHelper(#, #)',
            [_visitExpression(target), _visitExpressionList(args)]);
      } else {
        return runtimeCall('dsend(#, #, [#])',
            [_visitExpression(target), memberName, _visitExpressionList(args)]);
      }
    }

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

  @override
  visitIndexExpression(IndexExpression node) {
    var target = _getTarget(node);
    if (_useNativeJsIndexer(target.staticType)) {
      return JS.PropertyAccess(
          _visitExpression(target), _visitExpression(node.index));
    }
    return _emitOperatorCall(target, '[]', [node.index], node.staticElement);
  }

  // TODO(jmesserly): ideally we'd check the method and see if it is marked
  // `external`, but that doesn't work because it isn't in the element model.
  bool _useNativeJsIndexer(DartType type) =>
      findAnnotation(type.element, isJSAnnotation) != null;

  /// Gets the target of a [PropertyAccess], [IndexExpression], or
  /// [MethodInvocation]. These three nodes can appear in a [CascadeExpression].
  Expression _getTarget(Expression node) {
    if (node is IndexExpression) {
      return node.isCascaded ? _cascadeTarget : node.target;
    } else if (node is PropertyAccess) {
      return node.isCascaded ? _cascadeTarget : node.target;
    } else if (node is MethodInvocation) {
      return node.isCascaded ? _cascadeTarget : node.target;
    } else {
      return null;
    }
  }

  @override
  JS.Expression visitConditionalExpression(ConditionalExpression node) {
    return js.call('# ? # : #', [
      _visitTest(node.condition),
      _visitExpression(node.thenExpression),
      _visitExpression(node.elseExpression)
    ]);
  }

  @override
  JS.Expression visitThrowExpression(ThrowExpression node) {
    return runtimeCall('throw(#)', _visitExpression(node.expression));
  }

  @override
  JS.Expression visitRethrowExpression(RethrowExpression node) {
    return runtimeCall('rethrow(#)', _visitExpression(_catchParameter));
  }

  /// 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.Statement _visitScope(Statement stmt) {
    var result = _visitStatement(stmt);
    if (result is JS.ExpressionStatement &&
        result.expression is JS.VariableDeclarationList) {
      return JS.Block([result]);
    }
    return result;
  }

  @override
  JS.If visitIfStatement(IfStatement node) {
    return JS.If(_visitTest(node.condition), _visitScope(node.thenStatement),
        _visitScope(node.elseStatement));
  }

  @override
  JS.For visitForStatement(ForStatement node) {
    var init = _visitExpression(node.initialization) ??
        visitVariableDeclarationList(node.variables);
    var updaters = node.updaters;
    JS.Expression update;
    if (updaters != null && updaters.isNotEmpty) {
      update =
          JS.Expression.binary(updaters.map(_visitExpression).toList(), ',')
              .toVoidExpression();
    }
    var condition = _visitTest(node.condition);
    return JS.For(init, condition, update, _visitScope(node.body));
  }

  @override
  JS.While visitWhileStatement(WhileStatement node) {
    return JS.While(_visitTest(node.condition), _visitScope(node.body));
  }

  @override
  JS.Do visitDoStatement(DoStatement node) {
    return JS.Do(_visitScope(node.body), _visitTest(node.condition));
  }

  @override
  JS.Statement visitForEachStatement(ForEachStatement node) {
    if (node.awaitKeyword != null) {
      return _emitAwaitFor(node);
    }

    var init = _visitExpression(node.identifier);
    var iterable = _visitExpression(node.iterable);

    var body = _visitScope(node.body);
    if (init == null) {
      var id = _emitVariableDef(node.loopVariable.identifier);
      init = js.call('let #', id);
      if (_annotatedNullCheck(node.loopVariable.declaredElement)) {
        body = JS.Block([_nullParameterCheck(JS.Identifier(id.name)), body]);
      }
      if (variableIsReferenced(id.name, iterable)) {
        var temp = JS.TemporaryId('iter');
        return JS.Block(
            [iterable.toVariableDeclaration(temp), JS.ForOf(init, temp, body)]);
      }
    }
    return JS.ForOf(init, iterable, body);
  }

  JS.Statement _emitAwaitFor(ForEachStatement node) {
    // Emits `await for (var value in stream) ...`, which desugars as:
    //
    // let iter = new StreamIterator(stream);
    // try {
    //   while (await iter.moveNext()) {
    //     let 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 =
        rules.instantiateToBounds(_asyncStreamIterator) as InterfaceType;
    var createStreamIter = _emitInstanceCreationExpression(
        streamIterator.element.unnamedConstructor,
        streamIterator,
        () => [_visitExpression(node.iterable)]);
    var iter = JS.TemporaryId('iter');
    var variable = node.identifier ?? node.loopVariable.identifier;
    var init = _visitExpression(node.identifier);
    if (init == null) {
      init = js.call('let # = #.current', [_emitVariableDef(variable), iter]);
    } else {
      init = js.call('# = #.current', [init, iter]);
    }
    return js.statement(
        '{'
        '  let # = #;'
        '  try {'
        '    while (#) { #; #; }'
        '  } finally { #; }'
        '}',
        [
          iter,
          createStreamIter,
          JS.Yield(js.call('#.moveNext()', iter))
            ..sourceInformation = _nodeStart(variable),
          init,
          _visitStatement(node.body),
          JS.Yield(js.call('#.cancel()', iter))
            ..sourceInformation = _nodeStart(variable)
        ]);
  }

  @override
  visitBreakStatement(BreakStatement node) {
    var label = node.label;
    return JS.Break(label?.name);
  }

  @override
  visitContinueStatement(ContinueStatement node) {
    var label = node.label;
    return JS.Continue(label?.name);
  }

  @override
  visitTryStatement(TryStatement node) {
    var savedSuperAllowed = _superAllowed;
    _superAllowed = false;
    var finallyBlock = _visitStatement(node.finallyBlock)?.toBlock();
    _superAllowed = savedSuperAllowed;
    return JS.Try(_visitStatement(node.body).toBlock(),
        _visitCatch(node.catchClauses), finallyBlock);
  }

  JS.Catch _visitCatch(NodeList<CatchClause> clauses) {
    if (clauses == null || clauses.isEmpty) return null;

    // TODO(jmesserly): need a better way to get a temporary variable.
    // This could incorrectly shadow a user's name.
    var savedCatch = _catchParameter;

    var isSingleCatch =
        clauses.length == 1 && clauses.single.exceptionParameter != null;
    if (isSingleCatch) {
      // Special case for a single catch.
      _catchParameter = clauses.single.exceptionParameter;
    } else {
      _catchParameter = _createTemporary('e', types.dynamicType);
    }

    JS.Statement catchBody =
        js.statement('throw #;', _emitSimpleIdentifier(_catchParameter));
    for (var clause in clauses.reversed) {
      catchBody = _catchClauseGuard(clause, catchBody);
    }

    var catchVarDecl = _emitSimpleIdentifier(_catchParameter) as JS.Identifier;
    if (isSingleCatch) {
      catchVarDecl..sourceInformation = _nodeStart(_catchParameter);
    }
    _catchParameter = savedCatch;
    return JS.Catch(catchVarDecl, JS.Block([catchBody]));
  }

  JS.Statement _catchClauseGuard(CatchClause clause, JS.Statement otherwise) {
    var then = visitCatchClause(clause);

    // Discard following clauses, if any, as they are unreachable.
    if (clause.exceptionType == null) return then;

    // TODO(jmesserly): this is inconsistent with [visitIsExpression], which
    // has special case for typeof.
    var castType = _emitType(clause.exceptionType.type);

    return JS.If(
        js.call('#.is(#)', [castType, _emitSimpleIdentifier(_catchParameter)]),
        then,
        otherwise)
      ..sourceInformation = _nodeStart(clause);
  }

  /// Visits the catch clause body. This skips the exception type guard, if any.
  /// That is handled in [_visitCatch].
  @override
  JS.Statement visitCatchClause(CatchClause node) {
    var body = <JS.Statement>[];

    var savedCatch = _catchParameter;
    var vars = HashSet<String>();
    if (node.catchKeyword != null) {
      var name = node.exceptionParameter;
      if (name == _catchParameter) {
        vars.add(name.name);
      } else if (name != null) {
        vars.add(name.name);
        body.add(js.statement('let # = #;',
            [_emitVariableDef(name), _emitSimpleIdentifier(_catchParameter)]));
        _catchParameter = name;
      }
      var stackVar = node.stackTraceParameter;
      if (stackVar != null) {
        vars.add(stackVar.name);
        body.add(js.statement('let # = #.stackTrace(#);', [
          _emitVariableDef(stackVar),
          runtimeModule,
          _emitSimpleIdentifier(name)
        ]));
      }
    }

    body.add(_visitStatement(node.body).toScopedBlock(vars));
    _catchParameter = savedCatch;
    return JS.Statement.from(body);
  }

  @override
  JS.SwitchCase visitSwitchCase(SwitchCase node) {
    var expr = _visitExpression(node.expression);
    var body = _visitStatementList(node.statements);
    if (node.labels.isNotEmpty) {
      body.insert(0, js.comment('Unimplemented case labels: ${node.labels}'));
    }
    // TODO(jmesserly): make sure we are statically checking fall through
    return JS.SwitchCase(expr, JS.Block(body));
  }

  @override
  JS.SwitchCase visitSwitchDefault(SwitchDefault node) {
    var body = _visitStatementList(node.statements);
    if (node.labels.isNotEmpty) {
      body.insert(0, js.comment('Unimplemented case labels: ${node.labels}'));
    }
    // TODO(jmesserly): make sure we are statically checking fall through
    return JS.SwitchCase.defaultCase(JS.Block(body));
  }

  JS.SwitchCase _emitSwitchMember(SwitchMember node) {
    if (node is SwitchCase) {
      return visitSwitchCase(node);
    } else {
      return visitSwitchDefault(node as SwitchDefault);
    }
  }

  @override
  JS.Switch visitSwitchStatement(SwitchStatement node) => JS.Switch(
      _visitExpression(node.expression),
      node.members?.map(_emitSwitchMember)?.toList());

  @override
  JS.Statement visitLabeledStatement(LabeledStatement node) {
    var result = _visitStatement(node.statement);
    for (var label in node.labels.reversed) {
      result = JS.LabeledStatement(label.label.name, result);
    }
    return result;
  }

  @override
  visitIntegerLiteral(IntegerLiteral node) {
    var value = getLiteralBigIntValue(node);

    // Report an error if the integer literal cannot be exactly represented in
    // JS (because JS only has support for doubles).
    //
    // This applies regardless in an int or double context.
    var valueInJS = BigInt.from(value.toDouble());
    if (value != valueInJS) {
      assert(node.staticType == intClass.type || options.unsafeForceCompile,
          'int literals in double contexts should be checked by Analyzer.');

      var lexeme = node.literal.lexeme;
      var nearest = (lexeme.startsWith("0x") || lexeme.startsWith("0X"))
          ? '0x${valueInJS.toRadixString(16)}'
          : '$valueInJS';
      errors.add(AnalysisError(_currentCompilationUnit.source, node.offset,
          node.length, invalidJSInteger, [lexeme, nearest]));
    }
    return JS.LiteralNumber('$valueInJS');
  }

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

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

  @override
  visitSymbolLiteral(SymbolLiteral node) {
    return _emitConst(() => _emitDartSymbol(node.components.join('.')));
  }

  JS.Expression _emitDartSymbol(String name) {
    // TODO(vsm): Handle qualified symbols correctly.
    var last = name.substring(name.lastIndexOf('.') + 1);
    var jsName = js.string(name, "'");
    if (last.startsWith('_')) {
      var nativeSymbol = emitPrivateNameSymbol(currentLibrary, last);
      return js.call('new #.new(#, #)', [
        _emitConstructorAccess(privateSymbolClass.type),
        jsName,
        nativeSymbol
      ]);
    } else {
      return js
          .call('#.new(#)', [_emitConstructorAccess(types.symbolType), jsName]);
    }
  }

  @override
  JS.Expression visitListLiteral(ListLiteral node) {
    var elementType = (node.staticType as InterfaceType).typeArguments[0];
    if (!node.isConst) {
      return _emitList(elementType, _visitExpressionList(node.elements));
    }
    return _cacheConst(
        () => _emitConstList(elementType, _visitExpressionList(node.elements)));
  }

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

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

    // TODO(jmesserly): analyzer will usually infer `List<Object>` because
    // that is the least upper bound of the element types. So we rarely
    // generate a plain `List<dynamic>` anymore.
    if (itemType.isDynamic) return list;

    // Call `new JSArray<E>.of(list)`
    var arrayType = _jsArray.type.instantiate([itemType]);
    return js.call('#.of(#)', [_emitType(arrayType), list]);
  }

  @override
  visitMapLiteral(MapLiteral node) {
    emitEntries() {
      var entries = <JS.Expression>[];
      for (var e in node.entries) {
        entries.add(_visitExpression(e.key));
        entries.add(_visitExpression(e.value));
      }
      return entries;
    }

    var type = node.staticType as InterfaceType;
    if (!node.isConst) {
      var mapType = _emitMapImplType(type);
      if (node.entries.isEmpty) {
        return js.call('new #.new()', [mapType]);
      }
      return js.call('new #.from([#])', [mapType, emitEntries()]);
    }
    return _cacheConst(() => _emitConstMap(type, emitEntries()));
  }

  JS.Expression _emitConstMap(InterfaceType type, List<JS.Expression> entries) {
    var typeArgs = type.typeArguments;
    return runtimeCall('constMap(#, #, [#])',
        [_emitType(typeArgs[0]), _emitType(typeArgs[1]), entries]);
  }

  JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
    var typeArgs = type.typeArguments;
    if (typeArgs.isEmpty) return _emitType(type);
    identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
    type = identity ? identityHashMapImplType : linkedHashMapImplType;
    return _emitType(type.instantiate(typeArgs));
  }

  JS.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
    var typeArgs = type.typeArguments;
    if (typeArgs.isEmpty) return _emitType(type);
    identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
    type = identity ? identityHashSetImplType : linkedHashSetImplType;
    return _emitType(type.instantiate(typeArgs));
  }

  @override
  JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
      js.escapedString(node.value, '"');

  @override
  JS.Expression visitAdjacentStrings(AdjacentStrings node) {
    var nodes = node.strings;
    if (nodes == null || nodes.isEmpty) return null;
    return JS.Expression.binary(_visitExpressionList(nodes), '+');
  }

  @override
  JS.Expression visitStringInterpolation(StringInterpolation node) {
    var parts = <JS.Expression>[];
    for (var elem in node.elements) {
      if (elem is InterpolationString) {
        if (elem.value.isEmpty) continue;
        parts.add(js.escapedString(elem.value, '"'));
      } else {
        var e = (elem as InterpolationExpression).expression;
        var jsExpr = _visitExpression(e);
        parts.add(e.staticType == types.stringType && !isNullable(e)
            ? jsExpr
            : runtimeCall('str(#)', jsExpr));
      }
    }
    if (parts.isEmpty) return js.string('');
    return JS.Expression.binary(parts, '+');
  }

  @override
  visitInterpolationExpression(InterpolationExpression node) =>
      _visitExpression(node.expression);

  @override
  visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value);

  /// Visit a Dart [node] that produces a JS expression, and attaches a source
  /// location.
  // TODO(jmesserly): parameter type should be `Expression`
  JS.Expression _visitExpression(AstNode node) {
    if (node == null) return null;
    var e = node.accept<JS.Node>(this) as JS.Expression;
    e.sourceInformation ??= _nodeStart(node);
    return e;
  }

  /// Visit a Dart [node] that produces a JS statement, and marks its source
  /// location for debugging.
  JS.Statement _visitStatement(AstNode node) {
    if (node == null) return null;
    var s = node.accept<JS.Node>(this) as JS.Statement;
    if (s is! Block) s.sourceInformation = _nodeStart(node);
    return s;
  }

  /// Visits [nodes] with [_visitStatement].
  List<JS.Statement> _visitStatementList(Iterable<AstNode> nodes) {
    return nodes?.map(_visitStatement)?.toList();
  }

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

  /// 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(AstNode node) => _getLocation(node.offset);

  /// Gets the end position of [node] for use in source mapping.
  ///
  /// This is 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(AstNode node) {
    var loc = _getLocation(node.end);
    return loc != null ? NodeEnd(loc) : null;
  }

  /// Gets the end of a function for source mapping.
  ///
  /// JS wants a marking before the closing brace/semicolon, rather than after,
  /// so this adjusts appropriately (it uses [node.endToken.offset] rather than
  /// [node.end]).
  ///
  /// Every JS function should have an end marking for stepping out of it.
  /// Alternatively this can be supplied with [_functionSpan].
  NodeEnd _functionEnd(AstNode node) {
    var loc = _getLocation(node.endToken.offset);
    return loc != null ? NodeEnd(loc) : null;
  }

  /// Similar to [_functionEnd] but also marks the start of the function.
  ///
  /// This is used when we want to support hovering.
  NodeSpan _functionSpan(AstNode node) {
    var start = _getLocation(node.offset);
    var end = _getLocation(node.endToken.offset);
    return start != null && end != null ? NodeSpan(start, end) : null;
  }

  /// Combines [_nodeStart] and [_nodeEnd], used when we want to support
  /// hovering on the [node].
  NodeSpan _nodeSpan(AstNode node) {
    var start = _getLocation(node.offset);
    var end = _getLocation(node.end);
    return start != null && end != null ? NodeSpan(start, end) : 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.Expression expr, AstNode node) {
    var start = _getLocation(node.offset);
    var end = _getLocation(node.end);
    return start != null && end != null ? HoverComment(expr, start, end) : null;
  }

  SourceLocation _getLocation(int offset) {
    if (offset == -1) return null;
    var unit = _currentCompilationUnit;
    Uri fileUri;
    if (unit.source.isInSystemLibrary) {
      fileUri = unit.source.uri;
    } else {
      // TODO(jmesserly): this needs serious cleanup.
      // There does appear to be something strange going on with Analyzer
      // URIs if we try and use them directly on Windows.
      // See also compiler.dart placeSourceMap, which could use cleanup too.
      var sourcePath = unit.source.fullName;
      fileUri = sourcePath.startsWith('package:')
          ? Uri.parse(sourcePath)
          // TODO(jmesserly): shouldn't this be path.toUri?
          : Uri.file(sourcePath);
    }
    var loc = unit.lineInfo.getLocation(offset);
    return SourceLocation(offset,
        sourceUrl: fileUri,
        line: loc.lineNumber - 1,
        column: loc.columnNumber - 1);
  }

  /// 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.Expression _visitTest(Expression node) {
    if (node == null) return null;

    if (node is PrefixExpression && node.operator.lexeme == '!') {
      // TODO(leafp): consider a peephole opt for identical
      // and == here.
      return js.call('!#', _visitTest(node.operand));
    }
    if (node is ParenthesizedExpression) {
      return _visitTest(node.expression);
    }
    if (node is BinaryExpression) {
      JS.Expression shortCircuit(String code) {
        return js.call(code,
            [_visitTest(node.leftOperand), _visitTest(node.rightOperand)]);
      }

      var op = node.operator.type.lexeme;
      if (op == '&&') return shortCircuit('# && #');
      if (op == '||') return shortCircuit('# || #');
    }
    if (node is AsExpression && CoercionReifier.isImplicit(node)) {
      assert(node.staticType == types.boolType);
      return runtimeCall('dtest(#)', _visitExpression(node.expression));
    }
    var result = _visitExpression(node);
    if (isNullable(node)) result = runtimeCall('test(#)', result);
    return result;
  }

  /// 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.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) {
    return _emitMemberName(_getElementName(e),
        isStatic: e.isStatic,
        useExtension:
            useExtension ?? _extensionTypes.isNativeClass(e.enclosingElement),
        element: e);
  }

  /// 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.Expression _emitMemberName(String name,
      {DartType type,
      bool isStatic = false,
      bool useExtension,
      Element element}) {
    // Static members skip the rename steps and may require JS interop renames.
    if (isStatic) {
      return _emitStaticMemberName(name, element);
    }

    // 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 (element != null) {
      var runtimeName = getJSExportName(element);
      if (runtimeName != null) {
        var parts = runtimeName.split('.');
        if (parts.length < 2) return _propertyName(runtimeName);

        JS.Expression result = JS.Identifier(parts[0]);
        for (int i = 1; i < parts.length; i++) {
          result = JS.PropertyAccess(result, _propertyName(parts[i]));
        }
        return result;
      }
    }

    if (name.startsWith('_')) {
      return emitPrivateNameSymbol(currentLibrary, name);
    }

    useExtension ??= _isSymbolizedMember(type, name);
    // Rename members that conflict with standard JS members unless we are
    // actually try to access those JS members via interop.
    name = JS.memberNameForDartMember(name, _isExternal(element));
    if (useExtension) {
      return _getExtensionSymbolInternal(name);
    }
    return _propertyName(name);
  }

  JS.Expression _emitStaticMemberName(String name, [Element element]) {
    if (element != null) {
      var jsName = _emitJSInteropStaticMemberName(element);
      if (jsName != null) return jsName;
    }

    switch (name) {
      // Reserved for the compiler to do `x as T`.
      case 'as':
      // Reserved for the compiler to do implicit cast `T x = y`.
      case '_check':
      // Reserved for the SDK to compute `Type.toString()`.
      case 'name':
      // Reserved by JS, not a valid static member name.
      case 'prototype':
        name += '_';
        break;
      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);
  }

  /// 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.TemporaryId _getExtensionSymbolInternal(String name) {
    return _extensionSymbols.putIfAbsent(
        name,
        () => JS.TemporaryId(
            '\$${JS.friendlyNameForDartOperator[name] ?? name}'));
  }

  var _forwardingCache = HashMap<Element, Map<String, Element>>();

  Element _lookupForwardedMember(ClassElement element, String name) {
    // We only care about public methods.
    if (name.startsWith('_')) return null;

    var map = _forwardingCache.putIfAbsent(element, () => {});
    if (map.containsKey(name)) return map[name];

    // Note, for a public member, the library should not matter.
    var library = element.library;
    var member = element.lookUpMethod(name, library) ??
        element.lookUpGetter(name, library) ??
        element.lookUpSetter(name, library);
    var classMember = (member != null &&
            member.isSynthetic &&
            member is PropertyAccessorElement)
        ? member.variable
        : member;
    map[name] = classMember;
    return classMember;
  }

  /// 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(DartType type, String name) {
    while (type is TypeParameterType) {
      type = (type as TypeParameterType).bound;
    }
    if (type == null || type.isDynamic || type.isObject) {
      return isObjectMember(name);
    } else if (type is InterfaceType) {
      var interfaceType = jsTypeRep.getImplementationType(type) ?? type;
      var element = interfaceType.element;
      if (_extensionTypes.isNativeClass(element)) {
        var member = _lookupForwardedMember(element, name);

        // Fields on a native class are implicitly native.
        // Methods/getters/setters are marked external/native.
        if (member is FieldElement ||
            member is ExecutableElement && member.isExternal) {
          var jsName = getAnnotationName(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(element);
    } else if (type is FunctionType) {
      return true;
    }
    return false;
  }

  /// Returns the canonical name to refer to the Dart library.
  JS.Identifier emitLibraryName(LibraryElement library) {
    // It's either one of the libraries in this module, or it's an import.
    return _libraries[library] ??
        _imports.putIfAbsent(library,
            () => JS.TemporaryId(jsLibraryName(_libraryRoot, library)));
  }

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

  bool _isObjectMethodTearoff(String name) =>
      name == 'toString' || name == 'noSuchMethod';

  bool _isObjectMethodCall(String name, List<Expression> args) {
    if (name == 'toString') {
      return args.isEmpty;
    } else if (name == 'noSuchMethod') {
      return args.length == 1 && args[0] is! NamedExpression;
    }
    return false;
  }

  // TODO(leafp): Various analyzer pieces computed similar things.
  // Share this logic somewhere?
  DartType _getExpectedReturnType(ExecutableElement element) {
    FunctionType functionType = element.type;
    if (functionType == null) {
      return DynamicTypeImpl.instance;
    }
    var type = functionType.returnType;

    InterfaceType expectedType = null;
    if (element.isAsynchronous) {
      if (element.isGenerator) {
        // Stream<T> -> T
        expectedType = types.streamType;
      } else {
        // Future<T> -> T
        expectedType = types.futureType;
      }
    } else {
      if (element.isGenerator) {
        // Iterable<T> -> T
        expectedType = types.iterableType;
      } else {
        // T -> T
        return type;
      }
    }
    if (type.isDynamic) return type;
    if (type is InterfaceType &&
        (type.element == expectedType.element ||
            expectedType == types.futureType &&
                type.element == types.futureOrType.element)) {
      return type.typeArguments[0];
    }
    // TODO(leafp): The above only handles the case where the return type
    // is exactly Future/Stream/Iterable.  Handle the subtype case.
    return DynamicTypeImpl.instance;
  }

  JS.Expression _throwUnsafe(String message) => runtimeCall(
      'throw(Error(#))', js.escapedString("compile error: $message"));

  JS.Node _unreachable(Object node) {
    throw UnsupportedError('tried to generate an unreachable node: `$node`');
  }

  /// Unused, see methods for emitting declarations.
  @override
  visitAnnotation(node) => _unreachable(node);

  /// Unused, see [_emitArgumentList].
  @override
  visitArgumentList(ArgumentList node) => _unreachable(node);

  /// Unused, see [_emitFieldInitializers].
  @override
  visitAssertInitializer(node) => _unreachable(node);

  /// Not visited, but maybe they should be?
  /// See <https://github.com/dart-lang/sdk/issues/29347>
  @override
  visitComment(node) => _unreachable(node);

  /// Not visited, but maybe they should be?
  /// See <https://github.com/dart-lang/sdk/issues/29347>
  @override
  visitCommentReference(node) => _unreachable(node);

  /// Unused, handled by imports/exports.
  @override
  visitConfiguration(node) => _unreachable(node);

  /// Unused, see [_emitConstructor].
  @override
  visitConstructorDeclaration(node) => _unreachable(node);

  /// Unused, see [_emitFieldInitializers].
  @override
  visitConstructorFieldInitializer(node) => _unreachable(node);

  /// Unused, see [_emitRedirectingConstructor].
  @override
  visitRedirectingConstructorInvocation(node) => _unreachable(node);

  /// Unused. Handled in [visitForEachStatement].
  @override
  visitDeclaredIdentifier(node) => _unreachable(node);

  /// Unused, handled by imports/exports.
  @override
  visitDottedName(node) => _unreachable(node);

  /// Unused, handled by [_emitFormalParameter].
  @override
  visitDefaultFormalParameter(node) => _unreachable(node);

  /// Unused, handled by [_emitFormalParameter].
  @override
  visitSimpleFormalParameter(node) => _unreachable(node);

  /// Unused, handled by [_emitFormalParameter].
  @override
  visitFieldFormalParameter(node) => _unreachable(node);

  /// Unused, handled by [_emitFormalParameter].
  @override
  visitFunctionTypedFormalParameter(node) => _unreachable(node);

  /// Unused, handled by [visitEnumDeclaration].
  @override
  visitEnumConstantDeclaration(node) => _unreachable(node); // see

  /// Unused, see [_defineClass].
  @override
  visitExtendsClause(node) => _unreachable(node);

  /// Unused, see [_emitParameters].
  @override
  visitFormalParameterList(node) => _unreachable(node);

  /// Unused, handled by [visitMixinDeclaration].
  @override
  JS.Node visitOnClause(OnClause node) => _unreachable(node);

  /// Unused, handled by imports/exports.
  @override
  visitShowCombinator(node) => _unreachable(node);

  /// Unused, handled by imports/exports.
  @override
  visitHideCombinator(node) => _unreachable(node);

  /// Unused, see [_defineClass].
  @override
  visitImplementsClause(node) => _unreachable(node);

  /// Unused, handled by [visitStringInterpolation].
  @override
  visitInterpolationString(node) => _unreachable(node);

  /// Unused, labels are handled by containing statements.
  @override
  visitLabel(node) => _unreachable(node);

  /// Unused, handled by imports/exports.
  @override
  visitLibraryIdentifier(node) => _unreachable(node);

  /// Unused, see [visitMapLiteral].
  @override
  visitMapLiteralEntry(node) => _unreachable(node);

  /// Unused, see [_emitMethodDeclaration].
  @override
  visitMethodDeclaration(node) => _unreachable(node);

  /// Unused, these are not visited.
  @override
  visitNativeClause(node) => _unreachable(node);

  /// Unused, these are not visited.
  @override
  visitNativeFunctionBody(node) => _unreachable(node);

  /// Unused, handled by [_emitConstructor].
  @override
  visitSuperConstructorInvocation(node) => _unreachable(node);

  /// Unused, this can be handled when emitting the module if needed.
  @override
  visitScriptTag(node) => _unreachable(node);

  /// Unused, see [_emitType].
  @override
  visitTypeArgumentList(node) => _unreachable(node);

  /// Unused, see [_emitType].
  @override
  visitTypeParameter(node) => _unreachable(node);

  /// Unused, see [_emitType].
  @override
  visitTypeParameterList(node) => _unreachable(node);

  /// Unused, see [_defineClass].
  @override
  visitWithClause(node) => _unreachable(node);
}

/// Choose a canonical name from the [library] element.
///
/// This never uses the library's name (the identifier in the `library`
/// declaration) as it doesn't have any meaningful rules enforced.
String jsLibraryName(String libraryRoot, LibraryElement library) {
  var uri = library.source.uri;
  if (uri.scheme == 'dart') {
    return uri.path;
  }
  // TODO(vsm): This is not necessarily unique if '__' appears in a file name.
  var encodedSeparator = '__';
  String qualifiedPath;
  if (uri.scheme == 'package') {
    // Strip the package name.
    // TODO(vsm): This is not unique if an escaped '/'appears in a filename.
    // E.g., "foo/bar.dart" and "foo$47bar.dart" would collide.
    qualifiedPath = uri.pathSegments.skip(1).join(encodedSeparator);
  } else if (path.isWithin(libraryRoot, uri.toFilePath())) {
    qualifiedPath = path
        .relative(uri.toFilePath(), from: libraryRoot)
        .replaceAll(path.separator, encodedSeparator);
  } else {
    // We don't have a unique name.
    throw 'Invalid library root. $libraryRoot does not contain '
        '${uri.toFilePath()}';
  }
  return pathToJSIdentifier(qualifiedPath);
}

/// Debugger friendly name for a Dart Library.
String jsLibraryDebuggerName(String libraryRoot, LibraryElement library) {
  var uri = library.source.uri;
  // For package: and dart: uris show the entire
  if (uri.scheme == 'dart' || uri.scheme == 'package') return uri.toString();

  var filePath = uri.toFilePath();
  if (!path.isWithin(libraryRoot, filePath)) {
    throw 'Invalid library root. $libraryRoot does not contain '
        '${uri.toFilePath()}';
  }
  // Relative path to the library.
  return path.relative(filePath, from: libraryRoot);
}

/// 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.LiteralString _propertyName(String name) => js.string(name, "'");

// TODO(jacobr): we would like to do something like the following
// but we don't have summary support yet.
// bool _supportJsExtensionMethod(AnnotatedNode node) =>
//    _getAnnotation(node, "SupportJsExtensionMethod") != null;

/// A special kind of element created by the compiler, signifying a temporary
/// variable. These objects use instance equality, and should be shared
/// everywhere in the tree where they are treated as the same variable.
class TemporaryVariableElement extends LocalVariableElementImpl {
  final JS.Expression jsVariable;

  TemporaryVariableElement.forNode(Identifier name, this.jsVariable)
      : super.forNode(name);

  int get hashCode => identityHashCode(this);

  bool operator ==(Object other) => identical(this, other);
}

LibraryElement _getLibrary(AnalysisContext c, String uri) =>
    c.computeLibraryElement(c.sourceFactory.forUri(uri));

/// Returns `true` if [target] is a prefix for a deferred library and [name]
/// is "loadLibrary".
///
/// If so, the expression should be compiled to call the runtime's
/// "loadLibrary" helper function.
bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) {
  if (name.name != "loadLibrary") return false;

  if (target is! SimpleIdentifier) return false;
  var targetIdentifier = target as SimpleIdentifier;

  if (targetIdentifier.staticElement is! PrefixElement) return false;
  var prefix = targetIdentifier.staticElement as PrefixElement;

  // The library the prefix is referring to must come from a deferred import.
  var containingLibrary = resolutionMap
      .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
      .library;
  var imports = containingLibrary.getImportsWithPrefix(prefix);
  return imports.length == 1 && imports[0].isDeferred;
}

bool _annotatedNullCheck(Element e) =>
    e != null && findAnnotation(e, isNullCheckAnnotation) != null;

bool _reifyGeneric(Element e) =>
    e == null ||
    !e.source.isInSystemLibrary ||
    findAnnotation(
            e, (a) => isBuiltinAnnotation(a, '_js_helper', 'NoReifyGeneric')) ==
        null;

bool _reifyFunctionType(Element e) {
  if (e == null) return true;
  var library = e.library;
  if (!library.source.isInSystemLibrary) return true;
  // SDK libraries can skip reification if they request it.
  reifyFunctionTypes(DartObjectImpl a) =>
      isBuiltinAnnotation(a, '_js_helper', 'ReifyFunctionTypes');
  while (e != null) {
    var a = findAnnotation(e, reifyFunctionTypes);
    if (a != null) return a.getField('value').toBoolValue();
    e = e.enclosingElement;
  }
  return true;
}
