// 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/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
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/error/error.dart';
import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
import 'package:analyzer/src/dart/ast/utilities.dart' show UIAsCodeVisitorMixin;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/constant.dart'
    show DartObject, DartObjectImpl;
import 'package:analyzer/src/generated/resolver.dart'
    show TypeProvider, NamespaceBuilder;
import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/package_bundle_reader.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 'driver.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;
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
        UIAsCodeVisitorMixin<JS.Node>,
        NullableTypeInference,
        SharedCompiler<LibraryElement, ClassElement, InterfaceType,
            FunctionBody>
    implements
        AstVisitor<JS.Node> {
  final SummaryDataStore summaryData;

  final CompilerOptions options;
  final Dart2TypeSystem rules;

  /// Errors that were produced during compilation, if any.
  final ErrorCollector errors;

  JSTypeRep jsTypeRep;

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

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

  final _initializingFormalTemps = HashMap<ParameterElement, 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 internalSymbolClass;
  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>();

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

  final DeclaredVariables declaredVariables;

  /// Tracks the temporary variable used to build collections containing
  /// control flow [IfElement] and [ForElement] nodes. Should be saved when
  /// visiting a new control flow tree and restored after.
  JS.Expression _currentCollectionVariable;

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

  LibraryElement get currentLibrary => _currentElement.library;

  @override
  Uri get currentLibraryUri => _currentElement.librarySource.uri;

  @override
  FunctionBody get currentFunction => _currentFunction;

  @override
  InterfaceType get privateSymbolType => privateSymbolClass.type;

  @override
  InterfaceType get internalSymbolType => internalSymbolClass.type;

  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.
  JS.Program compile(List<CompilationUnit> compilationUnits) {
    _libraryRoot = options.libraryRoot;
    if (!_libraryRoot.endsWith(path.separator)) {
      _libraryRoot += path.separator;
    }

    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 libraries = compilationUnits
        .where((unit) {
          var library = unit.declaredElement.library;
          return unit.declaredElement == library.definingCompilationUnit;
        })
        .map((unit) => unit.declaredElement.library)
        .toList();

    var items = startModule(libraries);
    _typeTable = TypeTable(runtimeModule);

    // Collect all class/type Element -> Node mappings
    // in case we need to forward declare any classes.
    _declarationNodes = HashMap<TypeDefiningElement, AstNode>();
    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(types, declaredVariables,
          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);

    moduleItems.addAll(afterClassDefItems);
    afterClassDefItems.clear();

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

    // Declare imports and extension symbols
    emitImportsAndExtensionSymbols(items);

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

    return finishModule(items, options.moduleName);
  }

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

  /// If the element [e] uses JS interop, this returns the string containing the
  /// JS member's name, otherwise returns null.
  ///
  /// The member name is specified by the parameter to the `@JS()` annotation,
  /// defaulting to the member's name in Dart, for example:
  ///
  ///     @JS('foo')
  ///     external static bar(); // JS name is "foo"
  ///
  ///     @JS()
  ///     external static bar(); // JS name is "bar"
  ///
  ///     static bar() { /* ... */ } // not a JS member; JS name is null
  ///
  String _getJSInteropStaticMemberName(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 name;
  }

  /// 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.
  @override
  String jsLibraryName(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 {
      qualifiedPath = path
          .relative(uri.toFilePath(), from: _libraryRoot)
          .replaceAll(path.separator, encodedSeparator)
          .replaceAll('..', encodedSeparator);
    }
    return pathToJSIdentifier(qualifiedPath);
  }

  /// Debugger friendly name for a Dart Library.
  @override
  String jsLibraryDebuggerName(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();
    // Relative path to the library.
    return path.relative(filePath, from: _libraryRoot);
  }

  /// Returns true if the library [l] is dart:_runtime.
  @override
  bool isSdkInternalRuntime(LibraryElement l) {
    var uri = l.source.uri;
    return uri.scheme == 'dart' && uri.path == '_runtime';
  }

  @override
  String libraryToModule(LibraryElement 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;
  }

  /// 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 && _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
  JS.Expression visitIsExpression(IsExpression node) {
    return _emitIsExpression(
        node.expression, node.type.type, node.notOperator != null);
  }

  JS.Expression _emitIsExpression(Expression operand, DartType type,
      [bool negated = false]) {
    // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
    JS.Expression result;
    var lhs = _visitExpression(operand);
    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]);
    }

    return negated ? js.call('!#', result) : 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 {
      afterClassDefItems.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 = _hasUnnamedInheritedConstructor(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(classElem, 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];

      JS.Expression value = JS.Identifier('value');

      var setter = element.setter;
      if (setter != null) {
        var covariantParams = _classProperties.covariantParameters;
        var param = setter.parameters[0];
        if (param.isCovariant ||
            covariantParams != null && covariantParams.contains(param)) {
          value = _emitCast(param.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(classElem, 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(ClassElement c, JS.Expression className,
      String name, JS.Expression jsCtor) {
    jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
    return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
  }

  @override
  bool superclassHasStatic(ClassElement c, String name) {
    // Note: because we're only considering statics, we can ignore mixins.
    // We're only trying to find conflicts due to JS inheriting statics.
    var library = c.library;
    while (true) {
      var supertype = c.supertype;
      if (supertype == null) return false;
      c = supertype.element;
      for (var members in [c.methods, c.accessors]) {
        for (var m in members) {
          if (m.isStatic && m.name == name && m.isAccessibleIn(library)) {
            return true;
          }
        }
      }
    }
  }

  /// 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(classElem, _emitStaticClassName(e),
                _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(f), _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 && !_isExternal(f))
        .map((f) => members[f] as VariableDeclaration)
        .toList();
    if (lazyStatics.isNotEmpty) {
      // Because we filtered out external fields, we don't need to use
      // `_emitStaticClassName` here as we normally would.
      _declareBeforeUse(classElem);
      body.add(_emitLazyFields(_emitTopLevelName(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 = List.of(classElem.methods.where((m) => !m.isAbstract));
      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,
            // ignore: deprecated_member_use
            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 _hasUnnamedInheritedConstructor(ClassElement e) {
    if (e == null) return false;
    return _hasUnnamedConstructor(e) || _hasUnnamedSuperConstructor(e);
  }

  bool _hasUnnamedSuperConstructor(ClassElement e) {
    for (var mixin in e.mixins) {
      if (_hasUnnamedConstructor(mixin.element)) return true;
    }
    return _hasUnnamedInheritedConstructor(e.supertype?.element);
  }

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

  /// 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 (findAnnotation(param, isUndefinedAnnotation) != null) {
          defaultValue = null;
        } else if (paramNode != null) {
          var paramDefault = (paramNode as DefaultFormalParameter).defaultValue;
          if (paramDefault == null) {
            defaultValue = JS.LiteralNull();
          } 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);
  }

  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) {
    for (var n = node.parent; n != null; n = n.parent) {
      if (n is FunctionBody ||
          n is FieldDeclaration && n.staticKeyword == null ||
          n is ConstructorDeclaration && n.constKeyword == null) {
        return false;
      }
    }
    return true;
  }

  /// 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
        ? _emitSyncFunctionBody(element, parameters, body)
        : _emitGeneratorFunctionBody(element, parameters, body);

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

  /// Emits a `sync` function body (the default in Dart)
  ///
  /// To emit an `async`, `sync*`, or `async*` function body, use
  /// [_emitGeneratorFunctionBody] instead.
  JS.Block _emitSyncFunctionBody(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;
  }

  /// Emits an `async`, `sync*`, or `async*` function body.
  ///
  /// The body will perform these steps:
  ///
  /// - Run the argument initializers. These must be run synchronously
  ///   (e.g. covariance checks), and this helps performance.
  /// - Return the generator function, wrapped with the appropriate type
  ///   (`Future`, `Itearble`, and `Stream` respectively).
  ///
  /// To emit a `sync` function body (the default in Dart), use
  /// [_emitSyncFunctionBody] instead.
  JS.Block _emitGeneratorFunctionBody(ExecutableElement element,
      FormalParameterList parameters, FunctionBody body) {
    var savedFunction = _currentFunction;
    _currentFunction = body;

    var initArgs = _emitArgumentInitializers(element, parameters);
    var block = JS.Block([
      _emitGeneratorFunction(element, parameters, body).toReturn()
        ..sourceInformation = _nodeStart(body)
    ]);
    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.
      //
      // Note: we intentionally don't emit argument initializers here, because
      // they were already emitted outside of the generator expression.
      var savedFunction = _currentFunction;
      _currentFunction = body;
      var jsBody = _emitFunctionScopedBody(body, element);
      _currentFunction = savedFunction;

      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 (usesThisOrSuper(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;
    declareFn = toBoundFunctionStatement(fn, name);
    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);

    // For instance members, we add implicit-this.
    // For method tear-offs, we ensure it's a bound method.
    var target = isStatic ? _emitStaticClassName(element) : 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);
  }

  @override
  JS.Expression emitConstructorAccess(DartType type) {
    return _emitJSInterop(type.element) ?? _emitType(type);
  }

  /// Emits an expression referring to the class of static [member].
  ///
  /// Typically this is equivalent to [_declareBeforeUse] followed by
  /// [_emitTopLevelName] on the class, but if the member is external, then the
  /// native class name will be used, for direct access to the native member.
  JS.Expression _emitStaticClassName(ClassMemberElement member) {
    var c = member.enclosingElement;
    _declareBeforeUse(c);

    // A static native element should just forward directly to the JS type's
    // member, for example `Css.supports(...)` in dart:html should be replaced
    // by a direct call to the DOM API: `global.CSS.supports`.
    if (_isExternal(member)) {
      var nativeName = _extensionTypes.getNativePeers(c);
      if (nativeName.isNotEmpty) {
        return runtimeCall('global.#', nativeName[0]);
      }
    }
    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) {
      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 e) {
    return _emitType(instantiateElementTypeToBounds(rules, e));
  }

  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(field), 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)
            ..sourceInformation = _nodeSpan(target);
        }
      }
      if (member is MethodElement) {
        return _emitStaticClassName(member)
          ..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) {
      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> args,
      {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)) {
      return args.isEmpty ? js.call('{}') : args.single as JS.ObjectInitializer;
    }

    JS.Expression emitNew() {
      var name = element.name;
      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);
    }

    var result = emitNew();
    return isConst ? canonicalizeConstObject(result) : result;
  }

  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 _emitConstList(type.typeArguments[0],
            value.toListValue().map(_emitDartObject).toList());
      }
      if (type.element == types.mapType.element) {
        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);
        }
        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 _emitInstanceCreationExpression(ctor.constructor, type, 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, _currentElement);
    id.staticElement = idElement;
    id.staticType = type;
    setIsDynamicInvoke(id, dynamicInvoke ?? type.isDynamic);
    addTemporaryVariable(idElement, nullable: nullable);
    return id;
  }

  /// 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(#)', _emitSimpleIdentifier(_rethrowParameter));
  }

  /// 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.Statement visitIfStatement(IfStatement node) {
    return JS.If(_visitTest(node.condition), _visitScope(node.thenStatement),
        _visitScope(node.elseStatement));
  }

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

  JS.Statement _emitAwaitFor(ForEachParts forParts, JS.Statement jsBody) {
    // 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(forParts.iterable)]);
    var iter = JS.TemporaryId('iter');
    SimpleIdentifier variable;
    JS.Expression init;
    if (forParts is ForEachPartsWithIdentifier) {
      variable = forParts.identifier;
      init = js
          .call('# = #.current', [_visitExpression(forParts.identifier), iter]);
    } else if (forParts is ForEachPartsWithDeclaration) {
      variable = forParts.loopVariable.identifier;
      init = js.call('let # = #.current', [_emitVariableDef(variable), iter]);
    } else {
      throw new StateError('Unrecognized for loop parts');
    }
    return js.statement(
        '{'
        '  let # = #;'
        '  try {'
        '    while (#) { #; #; }'
        '  } finally { #; }'
        '}',
        [
          iter,
          createStreamIter,
          JS.Yield(js.call('#.moveNext()', iter))
            ..sourceInformation = _nodeStart(variable),
          init,
          jsBody,
          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;
    if (node.label != null) {
      var parent = node.parent;
      if (parent is SwitchCase) {
        // If this is the last statement in this case, and we're jumping to the
        // next statement in the following case, just omit the continue.  JS
        // will fall through.
        if (parent.statements.last == node) {
          var grandparent = parent.parent;
          if (grandparent is SwitchStatement) {
            var members = grandparent.members;
            for (int i = 0; i < members.length; ++i) {
              if (members[i] == parent) {
                if (i < members.length - 1) {
                  var next = members[i + 1];
                  if (next is SwitchMember &&
                      next.labels
                          .map((l) => l.label.name)
                          .contains(node.label.name)) {
                    return js.comment('continue to next case');
                  }
                }
                break;
              }
            }
          }
        }
      }
    }
    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;

    var caughtError = _createTemporary('e', types.dynamicType);
    var savedRethrow = _rethrowParameter;
    _rethrowParameter = caughtError;

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

    var stackTraceParameter =
        (clauses.length == 1 ? clauses[0].stackTraceParameter : null) ??
            (clauses.any((c) => c.stackTraceParameter != null)
                ? _createTemporary('st', types.dynamicType)
                : null);

    // Rethrow if the exception type didn't match.
    JS.Statement catchBody = JS.Throw(_emitSimpleIdentifier(caughtError));
    for (var clause in clauses.reversed) {
      catchBody = _catchClauseGuard(
          clause, catchBody, exceptionParameter, stackTraceParameter);
    }
    var catchStatements = [
      js.statement('let # = #.getThrown(#)', [
        _emitVariableDef(exceptionParameter),
        runtimeModule,
        _emitSimpleIdentifier(caughtError)
      ]),
    ];
    if (stackTraceParameter != null) {
      catchStatements.add(js.statement('let # = #.stackTrace(#)', [
        _emitVariableDef(stackTraceParameter),
        runtimeModule,
        _emitSimpleIdentifier(caughtError)
      ]));
    }
    catchStatements.add(catchBody);

    var catchVarDecl = _emitSimpleIdentifier(caughtError) as JS.Identifier;
    _rethrowParameter = savedRethrow;
    return JS.Catch(catchVarDecl, JS.Block(catchStatements));
  }

  JS.Statement _catchClauseGuard(
      CatchClause node,
      JS.Statement otherwise,
      SimpleIdentifier exceptionParameter,
      SimpleIdentifier stackTraceParameter) {
    var body = <JS.Statement>[];
    var vars = HashSet<String>();

    void declareVariable(SimpleIdentifier variable, SimpleIdentifier value) {
      if (variable == null) return;
      vars.add(variable.name);
      if (variable.name != value.name) {
        body.add(js.statement('let # = #',
            [visitSimpleIdentifier(variable), _emitSimpleIdentifier(value)]));
      }
    }

    if (node.catchKeyword != null) {
      declareVariable(node.exceptionParameter, exceptionParameter);
      declareVariable(node.stackTraceParameter, stackTraceParameter);
    }

    body.add(_visitStatement(node.body).toScopedBlock(vars));
    var then = JS.Statement.from(body);

    // Discard following clauses, if any, as they are unreachable.
    if (node.exceptionType == null ||
        rules.isSubtypeOf(types.objectType, node.exceptionType.type)) {
      return then;
    }

    var condition =
        _emitIsExpression(exceptionParameter, node.exceptionType.type);
    return JS.If(condition, then, otherwise)
      ..sourceInformation = _nodeStart(node);
  }

  @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(
          _currentCompilationUnit.lineInfo,
          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 emitDartSymbol(node.components.join('.'));
  }

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

  JS.Expression _emitSetLiteral(SetOrMapLiteral node) {
    var type = node.staticType as InterfaceType;
    var elementType = type.typeArguments[0];
    var jsElements = _visitCollectionElementList(node.elements, elementType);
    if (!node.isConst) {
      var setType = _emitType(type);
      if (node.elements.isEmpty) {
        return js.call('#.new()', [setType]);
      }
      return js.call('#.from([#])', [setType, jsElements]);
    }
    return cacheConst(
        runtimeCall('constSet(#, [#])', [_emitType(elementType), jsElements]));
  }

  JS.Expression _emitConstList(
      DartType elementType, List<JS.Expression> elements) {
    // dart.constList helper internally depends on _interceptors.JSArray.
    _declareBeforeUse(_jsArray);
    return cacheConst(
        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]);
  }

  JS.Expression _emitMapLiteral(SetOrMapLiteral node) {
    var type = node.staticType as InterfaceType;
    var elementType = type.typeArguments[0];
    var jsElements = _visitCollectionElementList(node.elements, elementType);
    if (!node.isConst) {
      var mapType = _emitMapImplType(type);
      if (node.elements.isEmpty) {
        return js.call('new #.new()', [mapType]);
      }
      return js.call('new #.from([#])', [mapType, jsElements]);
    }
    return _emitConstMap(type, jsElements);
  }

  JS.Expression _emitConstMap(InterfaceType type, List<JS.Expression> entries) {
    var typeArgs = type.typeArguments;
    return cacheConst(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;
  }

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

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

  /// Returns a [JS.Expression] for each [CollectionElement] in [nodes].
  ///
  /// Visits all [nodes] in order and nested [CollectionElement]s depth first
  /// to produce [JS.Expresison]s intended to be used when outputing a
  /// collection literal.
  ///
  /// [IfElement]s and [ForElement]s will be transformed into a spread of a
  /// self invoking function that reutrns a list.
  ///
  /// Example Dart:
  ///     [1, if(true) for (var i=2; i<10; i++) i, 10]
  ///
  /// JS:
  ///     [1, ...(() => {
  ///       let temp = JSArrayOfint().of([]);
  ///       if (true) for (let i = 2; i < 10; i++) temp.push(i);
  ///       return temp;
  ///     })(), 10]
  List<JS.Expression> _visitCollectionElementList(
      Iterable<CollectionElement> nodes, DartType elementType) {
    /// Returns [body] wrapped in a function and a call.
    ///
    /// Alternatively if [body] contains a yield, will wrap body in a gerarator
    /// fucntion, call it, and yield the result of [yieldType].
    /// TODO(nshahan) Move to share between compilers. Need to work out a common
    /// emitLibraryName().
    JS.Expression detectYieldAndCall(
        JS.Statement body, InterfaceType yieldType) {
      var finder = YieldFinder();
      body.accept(finder);
      if (finder.hasYield) {
        var genFn = JS.Fun([], body, isGenerator: true);
        var asyncLibrary = emitLibraryName(types.futureType.element.library);
        return JS.Yield(js.call(
            '#.async(#, #)', [asyncLibrary, _emitType(yieldType), genFn]));
      }
      return JS.Call(JS.ArrowFun([], body), []);
    }

    var expressions = <JS.Expression>[];
    for (var node in nodes) {
      if (_isUiAsCodeElement(node)) {
        // Create a temporary variable to build a new collection from.
        var previousCollectionVariable = _currentCollectionVariable;
        var arrayType = _jsArray.type.instantiate([elementType]);
        var temporaryIdentifier = _createTemporary('items', arrayType);
        _currentCollectionVariable = _emitSimpleIdentifier(temporaryIdentifier);
        var items = js.statement('let # = #',
            [_currentCollectionVariable, _emitList(elementType, [])]);

        // Build up a list for the control-flow-collections element and wrap in
        // a function call that returns the list.
        var functionBody = JS.Block([
          items,
          node.accept<JS.Node>(this),
          JS.Return(_currentCollectionVariable)
        ]);
        var functionCall = detectYieldAndCall(functionBody, arrayType);

        // Finally, spread the temporary control-flow-collections list.
        expressions.add(JS.Spread(functionCall));
        _currentCollectionVariable = previousCollectionVariable;
      } else if (node is MapLiteralEntry) {
        expressions.add(_visitExpression(node.key));
        expressions.add(_visitExpression(node.value));
      } else {
        expressions.add(_visitExpression(node));
      }
    }
    return expressions;
  }

  /// Visits [node] with [_visitExpression] and wraps the result in a call to
  /// append it to the list tracked by [_currentCollectionVariable].
  JS.Statement _visitNestedCollectionElement(CollectionElement node) {
    JS.Statement pushToCurrentCollection(Expression value) => js.statement(
        '#.push(#)', [_currentCollectionVariable, _visitExpression(value)]);

    if (node is MapLiteralEntry) {
      return JS.Block([
        pushToCurrentCollection(node.key),
        pushToCurrentCollection(node.value)
      ]);
    }

    return pushToCurrentCollection(node);
  }

  /// Returns `true` if [node] is a UI-as-Code [CollectionElement].
  bool _isUiAsCodeElement(node) =>
      node is IfElement || node is ForElement || node is SpreadElement;

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

  /// Emits the name of a static member, suitable for use in a JS property
  /// access when combined with [_emitStaticClassName].
  ///
  /// The member [name] should be passed, as well as its [element] when it's
  /// available. If the element is `external`, the element is used to statically
  /// resolve the JS interop/dart:html static member. Otherwise it is ignored.
  JS.Expression _emitStaticMemberName(String name, [Element element]) {
    if (element != null && _isExternal(element)) {
      var newName = getAnnotationName(element, isJSName) ??
          _getJSInteropStaticMemberName(element);
      if (newName != null) return js.escapedString(newName, "'");
    }

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

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

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

  /// Unused, see [_catchClauseGuard].
  @override
  visitCatchClause(CatchClause 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 [visitForStatement].
  @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 [visitSetOrMapLiteral].
  @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);

  JS.For _emitFor(ForParts forParts, JS.Statement body) {
    JS.Expression init;
    if (forParts is ForPartsWithExpression)
      init = _visitExpression(forParts.initialization);
    else if (forParts is ForPartsWithDeclarations) {
      init = visitVariableDeclarationList(forParts.variables);
    } else {
      throw new StateError('Unrecognized for loop parts');
    }
    JS.Expression update;
    if (forParts.updaters != null && forParts.updaters.isNotEmpty) {
      update = JS.Expression.binary(
              forParts.updaters.map(_visitExpression).toList(), ',')
          .toVoidExpression();
    }
    return JS.For(init, _visitTest(forParts.condition), update, body);
  }

  JS.Statement _emitForEach(ForEachParts forParts, JS.Statement jsBody) {
    var jsIterable = _visitExpression(forParts.iterable);
    JS.Expression jsLeftExpression;
    if (forParts is ForEachPartsWithIdentifier) {
      jsLeftExpression = _visitExpression(forParts.identifier);
    } else if (forParts is ForEachPartsWithDeclaration) {
      var id = _emitVariableDef(forParts.loopVariable.identifier);
      jsLeftExpression = js.call('let #', id);
      if (_annotatedNullCheck(forParts.loopVariable.declaredElement)) {
        jsBody =
            JS.Block([_nullParameterCheck(JS.Identifier(id.name)), jsBody]);
      }
      if (variableIsReferenced(id.name, jsIterable)) {
        var temp = JS.TemporaryId('iter');
        return JS.Block([
          jsIterable.toVariableDeclaration(temp),
          JS.ForOf(jsLeftExpression, temp, jsBody)
        ]);
      }
    } else {
      throw new StateError('Unrecognized for loop parts');
    }
    return JS.ForOf(jsLeftExpression, jsIterable, jsBody);
  }

  @override
  JS.Statement visitForElement(ForElement node) {
    var jsBody = _isUiAsCodeElement(node.body)
        ? node.body.accept(this)
        : _visitNestedCollectionElement(node.body);
    return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
  }

  @override
  JS.Statement visitIfElement(IfElement node) {
    var thenElement = _isUiAsCodeElement(node.thenElement)
        ? node.thenElement.accept(this)
        : _visitNestedCollectionElement(node.thenElement);

    JS.Statement elseElement;
    if (node.elseElement != null) {
      if (_isUiAsCodeElement(node.elseElement)) {
        elseElement = node.elseElement.accept<JS.Node>(this);
      } else {
        elseElement = _visitNestedCollectionElement(node.elseElement);
      }
    }

    return JS.If(_visitTest(node.condition), thenElement, elseElement);
  }

  @override
  visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) =>
      _unreachable(node);

  @override
  visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) =>
      _unreachable(node);

  @override
  JS.Statement visitForStatement(ForStatement node) =>
      _forAdaptor(node.forLoopParts, node.awaitKeyword, _visitScope(node.body));

  JS.Statement _forAdaptor(
      ForLoopParts forParts, Token awaitKeyword, JS.Statement jsBody) {
    /// Returns a new scoped block starting with [first] followed by [rest].
    ///
    /// Performs one level of scope flattening when [rest] is already a scoped
    /// block.
    JS.Block insertFirst(JS.Statement first, JS.Statement rest) {
      var bodyStatements = [first];
      if (rest is JS.Block) {
        bodyStatements.addAll(rest.statements);
      } else {
        bodyStatements.add(rest);
      }
      return JS.Block(bodyStatements);
    }

    if (forParts is ForParts) {
      return _emitFor(forParts, jsBody);
    } else if (forParts is ForEachParts) {
      // If needed, assert a cast inside the body before the variable is read.
      SimpleIdentifier variable;
      if (forParts is ForEachPartsWithIdentifier) {
        variable = forParts.identifier;
      } else if (forParts is ForEachPartsWithDeclaration) {
        variable = forParts.loopVariable.identifier;
      } else {
        throw new StateError('Unrecognized for loop parts');
      }
      var castType = getImplicitCast(variable);
      if (castType != null) {
        var castStatement =
            _emitCast(castType, _visitExpression(variable)).toStatement();
        jsBody = insertFirst(castStatement, jsBody);
      }
      if (awaitKeyword == null) {
        return _emitForEach(forParts, jsBody);
      } else {
        return _emitAwaitFor(forParts, jsBody);
      }
    }
    return _unreachable(forParts);
  }

  @override
  visitSetOrMapLiteral(SetOrMapLiteral node) =>
      node.isSet ? _emitSetLiteral(node) : _emitMapLiteral(node);

  @override
  JS.Statement visitSpreadElement(SpreadElement node) {
    /// Returns `true` if [node] is or is a child element of a map literal.
    bool isMap(AstNode node) {
      if (node is SetOrMapLiteral) return node.isMap;
      if (node is ListLiteral) return false;
      return isMap(node.parent);
    }

    /// Returns [expression] wrapped in an implict cast to [castType] or
    /// [expression] as provided if [castType] is `null` signifying that
    /// no cast is needed.
    JS.Expression wrapInImplicitCast(JS.Expression expression, castType) =>
        castType == null ? expression : _emitCast(castType, expression);

    /// Returns a statement spreading the elements of [expression] into
    /// [_currentCollectionVariable].
    ///
    /// Expects the collection literal containing [expression] to be a list or
    /// set literal. Inserts implicit casts to [elementCastType] for each
    /// element if needed.
    JS.Statement emitListOrSetSpread(
        JS.Expression expression, DartType elementCastType) {
      var forEachTemp =
          _emitSimpleIdentifier(_createTemporary('i', types.dynamicType));
      return js.statement('#.forEach((#) => #.push(#))', [
        expression,
        forEachTemp,
        _currentCollectionVariable,
        wrapInImplicitCast(forEachTemp, elementCastType)
      ]);
    }

    /// Returns a statement spreading the key/value pairs of [expression]
    /// into [_currentCollectionVariable].
    ///
    /// Expects the collection literal containing [expression] to be a map
    /// literal. Inserts implicit casts to [keyCastType] for keys and
    /// [valueCastType] for values if needed.
    JS.Statement emitMapSpread(JS.Expression expression, DartType keyCastType,
        DartType valueCastType) {
      var keyTemp =
          _emitSimpleIdentifier(_createTemporary('k', types.dynamicType));
      var valueTemp =
          _emitSimpleIdentifier(_createTemporary('v', types.dynamicType));
      return js.statement('#.forEach((#, #) => {#.push(#); #.push(#)})', [
        expression,
        keyTemp,
        valueTemp,
        _currentCollectionVariable,
        wrapInImplicitCast(keyTemp, keyCastType),
        _currentCollectionVariable,
        wrapInImplicitCast(valueTemp, valueCastType)
      ]);
    }

    /// Appends all elements in [expression] to the collection being built.
    ///
    /// Uses implict cast information from [node] to insert the correct casts
    /// for the collection elements when spreading. Inspects parents of [node]
    /// to determine the type of the enclosing collection literal.
    JS.Statement emitSpread(JS.Expression expression, Expression node) {
      expression = wrapInImplicitCast(expression, getImplicitCast(node));

      // Start searching for a map literal at the parent of the SpreadElement.
      if (isMap(node.parent.parent)) {
        return emitMapSpread(expression, getImplicitSpreadKeyCast(node),
            getImplicitSpreadValueCast(node));
      }
      return emitListOrSetSpread(expression, getImplicitSpreadCast(node));
    }

    /// Emits a null check on [expression] then appends all elements to the
    /// collection being built.
    ///
    /// Uses implict cast information from [node] to insert the correct casts
    /// for the collection elements when spreading. Inspects parents of [node]
    /// to determine the type of the enclosing collection literal.
    JS.Statement emitNullSafeSpread(JS.Expression expression, Expression node) {
      // TODO(nshahan) Could optimize out if we know the value is null.
      var spreadItems =
          _emitSimpleIdentifier(_createTemporary('items', getStaticType(node)));
      return JS.Block([
        js.statement('let # = #', [spreadItems, expression]),
        js.statement(
            'if (# != null) #', [spreadItems, emitSpread(spreadItems, node)])
      ]);
    }

    var expression = _visitExpression(node.expression);
    return node.beginToken.lexeme == '...?'
        ? emitNullSafeSpread(expression, node.expression)
        : emitSpread(expression, node.expression);
  }

  @override
  visitForPartsWithDeclarations(ForPartsWithDeclarations node) =>
      _unreachable(node);

  @override
  visitForPartsWithExpression(ForPartsWithExpression node) =>
      _unreachable(node);
}

// 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, Element enclosingElement)
      : super.forNode(name) {
    this.enclosingElement = enclosingElement is ElementHandle
        ? enclosingElement.actualElement
        : enclosingElement;
  }

  int get hashCode => identityHashCode(this);

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

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