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

part of dart2js.js_emitter.startup_emitter.model_emitter;

/// The fast startup emitter's goal is to minimize the amount of work that the
/// JavaScript engine has to do before it can start running user code.
///
/// Whenever possible, the emitter uses object literals instead of updating
/// objects.
///
/// Example:
///
///     // Holders are initialized directly with the classes and static
///     // functions.
///     var A = { Point: function Point(x, y) { this.x = x; this.y = y },
///               someStaticFunction: function someStaticFunction() { ... } };
///
///     // Class-behavior is emitted in a prototype object that is directly
///     // assigned:
///     A.Point.prototype = { distanceTo: function(other) { ... } };
///
///     // Inheritance is achieved by updating the prototype objects (hidden in
///     // a helper function):
///     A.Point.prototype.__proto__ = H.Object.prototype;
///
/// The emitter doesn't try to be clever and emits everything beforehand. This
/// increases the output size, but improves performance.
///
// The code relies on the fact that all Dart code is inside holders. As such
// we can use "global" names however we want. As long as we don't shadow
// JavaScript variables (like `Array`) we are free to chose whatever variable
// names we want. Furthermore, the pretty-printer minifies local variables, thus
// reducing their size.
const String _mainBoilerplate = '''
(function dartProgram() {

if (#startupMetrics) {
  // Stash the metrics on the main unit IIFE.
  // TODO(sra): When the JavaScript local renamer is more intelligent, we can
  // simply use a local variable.
  (dartProgram.$STARTUP_METRICS = ${ModelEmitter.startupMetricsGlobal})
      .add("dartProgramMs");
}

// Copies the own properties from [from] to [to].
function copyProperties(from, to) {
  var keys = Object.keys(from);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    to[key] = from[key];
  }
}
// Copies the own properties from [from] to [to] if not already present in [to].
function mixinProperties(from, to) {
  var keys = Object.keys(from);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    if (!to.hasOwnProperty(key)) {
      to[key] = from[key];
    }
  }
}

// Only use direct proto access to construct the prototype chain (instead of
// copying properties) on platforms where we know it works well (Chrome / d8).
var supportsDirectProtoAccess = #directAccessTestExpression;

// Sets the name property of functions, if the JS engine doesn't set the name
// itself.
// As of 2018 only IE11 doesn't set the name.
function setFunctionNamesIfNecessary(holders) {
  function t(){};
  if (typeof t.name == "string") return;

  for (var i = 0; i < holders.length; i++) {
    var holder = holders[i];
    var keys = Object.keys(holder);
    for (var j = 0; j < keys.length; j++) {
      var key = keys[j];
      var f = holder[key];
      if (typeof f == "function") f.name = key;
    }
  }
}

// Makes [cls] inherit from [sup].
// On Chrome, Firefox and recent IEs this happens by updating the internal
// proto-property of the classes 'prototype' field.
// Older IEs use `Object.create` and copy over the properties.
function inherit(cls, sup) {
  // cls.prototype.constructor carries the cached RTI. We could avoid this by
  // using ES6 classes, but the side effects of this need to be tested.
  cls.prototype.constructor = cls;
  cls.prototype[#operatorIsPrefix + cls.name] = cls;

  // The superclass is only null for the Dart Object.
  if (sup != null) {
    if (supportsDirectProtoAccess) {
      // Firefox doesn't like to update the prototypes, but when setting up
      // the hierarchy chain it's ok.
      cls.prototype.__proto__ = sup.prototype;
      return;
    }
    var clsPrototype = Object.create(sup.prototype);
    copyProperties(cls.prototype, clsPrototype);
    cls.prototype = clsPrototype;
  }
}

// Batched version of [inherit] for multiple classes from one superclass.
function inheritMany(sup, classes) {
  for (var i = 0; i < classes.length; i++) {
    inherit(classes[i], sup);
  }
}

// Mixes in the properties of [mixin] into [cls].
function mixin(cls, mixin) {
  mixinProperties(mixin.prototype, cls.prototype);
  cls.prototype.constructor = cls;
}

// Creates a lazy field.
//
// A lazy field has a storage entry, [name], which holds the value, and a
// getter ([getterName]) to access the field. If the field wasn't set before
// the first access, it is initialized with the [initializer].
function lazyOld(holder, name, getterName, initializer) {
  var uninitializedSentinel = holder;
  holder[name] = uninitializedSentinel;
  holder[getterName] = function() {
    holder[getterName] = function() { #cyclicThrow(name) };
    var result;
    var sentinelInProgress = initializer;
    try {
      if (holder[name] === uninitializedSentinel) {
        result = holder[name] = sentinelInProgress;
        result = holder[name] = initializer();
      } else {
        result = holder[name];
      }
    } finally {
      // Use try-finally, not try-catch/throw as it destroys the stack
      // trace.
      if (result === sentinelInProgress) {
        // The lazy static (holder[name]) might have been set to a different
        // value. According to spec we still have to reset it to null, if
        // the initialization failed.
        holder[name] = null;
      }
      // TODO(floitsch): for performance reasons the function should probably
      // be unique for each static.
      holder[getterName] = function() { return this[name]; };
    }
    return result;
  };
}

// Creates a lazy field that uses non-nullable initialization semantics.
//
// A lazy field has a storage entry, [name], which holds the value, and a
// getter ([getterName]) to access the field. If the field wasn't set before
// the first access, it is initialized with the [initializer].
function lazy(holder, name, getterName, initializer) {
  var uninitializedSentinel = holder;
  holder[name] = uninitializedSentinel;
  holder[getterName] = function() {
    if (holder[name] === uninitializedSentinel) {
      holder[name] = initializer();
    }
    holder[getterName] = function() { return this[name]; };
    return holder[name];
  };
}

// Creates a lazy final field that uses non-nullable initialization semantics.
//
// A lazy field has a storage entry, [name], which holds the value, and a
// getter ([getterName]) to access the field. If the field wasn't set before
// the first access, it is initialized with the [initializer].
function lazyFinal(holder, name, getterName, initializer) {
  var uninitializedSentinel = holder;
  holder[name] = uninitializedSentinel;
  holder[getterName] = function() {
    if (holder[name] === uninitializedSentinel) {
      var value = initializer();
      if (holder[name] !== uninitializedSentinel) {
        #throwLateFieldADI(name);
      }
      holder[name] = value;
    }
    holder[getterName] = function() { return this[name]; };
    return holder[name];
  };
}

// Given a list, marks it as constant.
//
// The runtime ensures that const-lists cannot be modified.
function makeConstList(list) {
  // By assigning a function to the properties they become part of the
  // hidden class. The actual values of the fields don't matter, since we
  // only check if they exist.
  list.immutable\$list = Array;
  list.fixed\$length = Array;
  return list;
}

function convertToFastObject(properties) {
  // Create an instance that uses 'properties' as prototype. This should
  // make 'properties' a fast object.
  function t() {}
  t.prototype = properties;
  new t();
  return properties;
}

function convertAllToFastObject(arrayOfObjects) {
  for (var i = 0; i < arrayOfObjects.length; ++i) {
    convertToFastObject(arrayOfObjects[i]);
  }
}

// This variable is used by the tearOffCode to guarantee unique functions per
// tear-offs.
var functionCounter = 0;
#tearOffCode;

// Each deferred hunk comes with its own types which are added to the end
// of the types-array.
// The `funType` passed to the `installTearOff` function below is relative to
// the hunk the function comes from. The `typesOffset` variable encodes the
// offset at which the new types will be added.
var typesOffset = 0;

/// Collect and canonicalize tear-off parameters.
///
/// [container] is either the `prototype` of a class constructor, or the holder
/// for static functions.
///
/// [funsOrNames] is an array of strings or functions. If it is a
/// name, then the function should be fetched from the container. The first
/// entry in that array *must* be a string.
// TODO(sra): It might be more readable to manually inline and simplify at the
// two calls. It would need to be assessed as it would likely make the object
// references polymorphic.
function tearOffParameters(
    container, isStatic, isIntercepted,
    requiredParameterCount, optionalParameterDefaultValues,
    callNames, funsOrNames, funType, applyIndex, needsDirectAccess) {
  if (typeof funType == "number") {
    // The [funType] can be a string type recipe or an index into the types
    // table.  If it points into the types-table we need to update the index, in
    // case the tear-off is part of a deferred hunk.
    funType += typesOffset;
  }
  return {
    #tpContainer: container,
    #tpIsStatic: isStatic,
    #tpIsIntercepted: isIntercepted,
    #tpRequiredParameterCount: requiredParameterCount,
    #tpOptionalParamaterDefaultValues: optionalParameterDefaultValues,
    #tpCallNames: callNames,
    #tpFunctionsOrNames: funsOrNames,
    #tpFunctionType: funType,
    #tpApplyIndex: applyIndex || 0,
    #tpNeedsDirectAccess: needsDirectAccess,
  }
}

/// Stores the static tear-off getter-function in the [holder]'s [getterName]
/// property.
function installStaticTearOff(
    holder, getterName,
    requiredParameterCount, optionalParameterDefaultValues,
    callNames, funsOrNames, funType, applyIndex) {
  // TODO(sra): Specialize for very common simple cases.
  var parameters = tearOffParameters(
      holder, true, false,
      requiredParameterCount, optionalParameterDefaultValues,
      callNames, funsOrNames, funType, applyIndex, false);
  var getterFunction = staticTearOffGetter(parameters);
  // TODO(sra): Returning [getterFunction] would be more versatile. We might
  // want to store the static tearoff getter in a different holder, or in no
  // holder if it is immediately called from the constant pool and otherwise
  // unreferenced.
  holder[getterName] = getterFunction;
}

/// Stores the instance tear-off getter-function in the [prototype]'s
/// [getterName] property.
function installInstanceTearOff(
    prototype, getterName, isIntercepted,
    requiredParameterCount, optionalParameterDefaultValues,
    callNames, funsOrNames, funType, applyIndex, needsDirectAccess) {
  isIntercepted = !!isIntercepted; // force to Boolean.
  var parameters = tearOffParameters(
      prototype, false, isIntercepted,
      requiredParameterCount, optionalParameterDefaultValues,
      callNames, funsOrNames, funType, applyIndex, !!needsDirectAccess);
  var getterFunction = instanceTearOffGetter(isIntercepted, parameters);
  prototype[getterName] = getterFunction;
}

// Instead of setting the interceptor tags directly we use this update
// function. This makes it easier for deferred fragments to contribute to the
// embedded global.
function setOrUpdateInterceptorsByTag(newTags) {
  var tags = #embeddedInterceptorTags;
  if (!tags) {
    #embeddedInterceptorTags = newTags;
    return;
  }
  copyProperties(newTags, tags);
}

// Instead of setting the leaf tags directly we use this update
// function. This makes it easier for deferred fragments to contribute to the
// embedded global.
function setOrUpdateLeafTags(newTags) {
  var tags = #embeddedLeafTags;
  if (!tags) {
    #embeddedLeafTags = newTags;
    return;
  }
  copyProperties(newTags, tags);
}

// Updates the types embedded global.
function updateTypes(newTypes) {
  var types = #embeddedTypes;
  var length = types.length;
  // The tear-off function uses another 'typesOffset' value cached in
  // [initializeDeferredHunk] so [updateTypes] can be called either before or
  // after the tearoffs have been installed.
  types.push.apply(types, newTypes);
  return length;
}

// Updates the given holder with the properties of the [newHolder].
// This function is used when a deferred fragment is initialized.
function updateHolder(holder, newHolder) {
  copyProperties(newHolder, holder);
  return holder;
}

var #hunkHelpers = (function(){
  var mkInstance = function(
      isIntercepted, requiredParameterCount, optionalParameterDefaultValues,
      callNames, applyIndex) {
    return function(container, getterName, name, funType) {
      return installInstanceTearOff(
          container, getterName, isIntercepted,
          requiredParameterCount, optionalParameterDefaultValues,
          callNames, [name], funType, applyIndex,
          /*needsDirectAccess:*/ false);
    }
  },

  mkStatic = function(
      requiredParameterCount, optionalParameterDefaultValues,
      callNames, applyIndex) {
    return function(container, getterName, name, funType) {
      return installStaticTearOff(
          container, getterName,
          requiredParameterCount, optionalParameterDefaultValues,
          callNames, [name], funType, applyIndex);
    }
  };

  // TODO(sra): Minify properties of 'hunkHelpers'.
  return {
    inherit: inherit,
    inheritMany: inheritMany,
    mixin: mixin,
    installStaticTearOff: installStaticTearOff,
    installInstanceTearOff: installInstanceTearOff,

        // Unintercepted methods.
    _instance_0u: mkInstance(0, 0, null, [#call0selector], 0),
    _instance_1u: mkInstance(0, 1, null, [#call1selector], 0),
    _instance_2u: mkInstance(0, 2, null, [#call2selector], 0),

        // Intercepted methods.
    _instance_0i: mkInstance(1, 0, null, [#call0selector], 0),
    _instance_1i: mkInstance(1, 1, null, [#call1selector], 0),
    _instance_2i: mkInstance(1, 2, null, [#call2selector], 0),

        // Static methods.
    _static_0: mkStatic(0, null, [#call0selector], 0),
    _static_1: mkStatic(1, null, [#call1selector], 0),
    _static_2: mkStatic(2, null, [#call2selector], 0),

    makeConstList: makeConstList,
    lazy: lazy,
    lazyFinal: lazyFinal,
    lazyOld: lazyOld,
    updateHolder: updateHolder,
    convertToFastObject: convertToFastObject,
    setFunctionNamesIfNecessary: setFunctionNamesIfNecessary,
    updateTypes: updateTypes,
    setOrUpdateInterceptorsByTag: setOrUpdateInterceptorsByTag,
    setOrUpdateLeafTags: setOrUpdateLeafTags,
  };
})();

// Every deferred hunk (i.e. fragment) is a function that we can invoke to
// initialize it. At this moment it contributes its data to the main hunk.
function initializeDeferredHunk(hunk) {
  // Update the typesOffset for the next deferred library.
  typesOffset = #embeddedTypes.length;

  // TODO(floitsch): extend natives.
  hunk(hunkHelpers, #embeddedGlobalsObject, holders, #staticState);
}

if (#isTrackingAllocations) {
  var allocations = #deferredGlobal['allocations'] = {};
}

// Creates the holders.
#holders;

// If the name is not set on the functions, do it now.
hunkHelpers.setFunctionNamesIfNecessary(holders);

// TODO(floitsch): we should build this object as a literal.
var #staticStateDeclaration = {};

// Sets the prototypes of classes.
#prototypes;
// Sets aliases of methods (on the prototypes of classes).
#aliases;
// Installs the tear-offs of functions.
#tearOffs;
// Builds the inheritance structure.
#inheritance;

// Emits the embedded globals. This needs to be before constants so the embedded
// global type resources are available for generating constants.
#embeddedGlobalsPart1;

// Adds the subtype rules for the new RTI.
#typeRules;

// Adds the variance table for the new RTI.
#variances;

// Shared strings need to be initialized before constants.
#sharedStrings;

// Shared types need to be initialized before constants.
#sharedTypeRtis;

// Instantiates all constants.
#constants;

// Adds to the embedded globals. A few globals refer to constants.
#embeddedGlobalsPart2;

// Initializes the static non-final fields (with their constant values).
#staticNonFinalFields;
// Creates lazy getters for statics that must run initializers on first access.
#lazyStatics;

// Sets up the native support.
// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
#nativeSupport;

// Sets up the js-interop support.
#jsInteropSupport;

// Ensure holders are in fast mode, now we have finished adding things.
convertAllToFastObject(holders);
convertToFastObject(#staticState);

// Invokes main (making sure that it records the 'current-script' value).
#invokeMain;
})();
''';

/// An expression that returns `true` if `__proto__` can be assigned to stitch
/// together a prototype chain, and the performance is good.
const String _directAccessTestExpression = r'''
  (function () {
    var cls = function () {};
    cls.prototype = {'p': {}};
    var object = new cls();
    if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
      return false;

    try {
      // Are we running on a platform where the performance is good?
      // (i.e. Chrome or d8).

      // Chrome userAgent?
      if (typeof navigator != "undefined" &&
          typeof navigator.userAgent == "string" &&
          navigator.userAgent.indexOf("Chrome/") >= 0) return true;
      // d8 version() looks like "N.N.N.N", jsshell version() like "N".
      if (typeof version == "function" &&
          version.length == 0) {
        var v = version();
        if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true;
      }
    } catch(_) {}

    return false;
  })()
''';

/// Soft-deferred fragments are built similarly to the main fragment.

/// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
///
/// However, at specific moments they need to contribute their data.
/// For example, once the holders have been created, they are included into
/// the main holders.
///
/// This template is used for Dart 2.
const String _deferredBoilerplate = '''
function(hunkHelpers, #embeddedGlobalsObject, holdersList, #staticState) {

// Builds the holders. They only contain the data for new holders.
// If names are not set on functions, we do it now. Finally, updates the
// holders of the main-fragment. Uses the provided holdersList to access the
// main holders.
// The local holders are replaced by the combined holders. This is necessary
// for the inheritance setup below.
#updateHolders;
// Sets the prototypes of the new classes.
#prototypes;
// Add signature function types and compute the types offset in `init.types`.
// These can only refer to regular classes and in Dart 2 only closures have
// function types so the `typesOffset` has been safely computed before it's
// referred in the signatures of the `closures` below.
var #typesOffset = hunkHelpers.updateTypes(#types);
#closures;
// Sets aliases of methods (on the prototypes of classes).
#aliases;
// Installs the tear-offs of functions.
#tearOffs;
// Builds the inheritance structure.
#inheritance;

// Adds the subtype rules for the new RTI.
#typeRules;

// Adds the variance table for the new RTI.
#variances;

#sharedStrings;

#sharedTypeRtis;
// Instantiates all constants of this deferred fragment.
// Note that the constant-holder has been updated earlier and storing the
// constant values in the constant-holder makes them available globally.
#constants;
// Initializes the static non-final fields (with their constant values).
#staticNonFinalFields;
// Creates lazy getters for statics that must run initializers on first access.
#lazyStatics;

// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
#nativeSupport;
}''';

/// This class builds a JavaScript tree for a given fragment.
///
/// A fragment is generally written into a separate file so that it can be
/// loaded dynamically when a deferred library is loaded.
///
/// This class is stateless and can be reused for different fragments.
class FragmentEmitter {
  final CompilerOptions _options;
  final DumpInfoTask _dumpInfoTask;
  final Namer _namer;
  final Emitter _emitter;
  final ConstantEmitter _constantEmitter;
  final ModelEmitter _modelEmitter;
  final NativeEmitter _nativeEmitter;
  final JClosedWorld _closedWorld;
  final CodegenWorld _codegenWorld;
  RecipeEncoder _recipeEncoder;
  RulesetEncoder _rulesetEncoder;
  DeferredHolderExpressionFinalizer _holderFinalizer;

  ClassHierarchy get _classHierarchy => _closedWorld.classHierarchy;
  CommonElements get _commonElements => _closedWorld.commonElements;
  DartTypes get _dartTypes => _closedWorld.dartTypes;
  JElementEnvironment get _elementEnvironment =>
      _closedWorld.elementEnvironment;
  RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;

  js.Name _call0Name, _call1Name, _call2Name;
  js.Name get call0Name =>
      _call0Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX0);
  js.Name get call1Name =>
      _call1Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX1);
  js.Name get call2Name =>
      _call2Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX2);
  List<js.Name> _callNamesByArity;
  List<js.Name> get callNamesByArity =>
      _callNamesByArity ??= [call0Name, call1Name, call2Name];

  FragmentEmitter(
      this._options,
      this._dumpInfoTask,
      this._namer,
      this._emitter,
      this._constantEmitter,
      this._modelEmitter,
      this._nativeEmitter,
      this._closedWorld,
      this._codegenWorld)
      : _holderFinalizer = _options.features.newHolders.isEnabled
            ? DeferredHolderExpressionFinalizerImpl(_closedWorld.commonElements)
            : LegacyDeferredHolderExpressionFinalizerImpl(
                _closedWorld.commonElements) {
    _recipeEncoder = RecipeEncoderImpl(
        _closedWorld,
        _options.disableRtiOptimization
            ? TrivialRuntimeTypesSubstitutions(_closedWorld)
            : RuntimeTypesImpl(_closedWorld),
        _closedWorld.nativeData,
        _closedWorld.commonElements);
    _rulesetEncoder =
        RulesetEncoder(_closedWorld.dartTypes, _emitter, _recipeEncoder);
  }

  js.Expression generateEmbeddedGlobalAccess(String global) =>
      _emitter.generateEmbeddedGlobalAccess(global);

  js.Expression generateConstantReference(ConstantValue value) =>
      _modelEmitter.generateConstantReference(value);

  js.Expression classReference(Class cls) {
    // TODO(joshualitt): This should be generated by
    // [DeferredHolderExpressionFinalizer].
    return js
        .js('#.#', [_namer.readGlobalObjectForClass(cls.element), cls.name]);
  }

  void registerEntityAst(Entity entity, js.Node code, {LibraryEntity library}) {
    _dumpInfoTask.registerEntityAst(entity, code);
    // TODO(sigmund): stop recoding associations twice, dump-info already
    // has library to element dependencies to recover this data.
    if (library != null) _dumpInfoTask.registerEntityAst(library, code);
  }

  PreFragment emitPreFragment(DeferredFragment fragment, bool estimateSize) {
    var classPrototypes = emitPrototypes(fragment, includeClosures: false);
    var closurePrototypes = emitPrototypes(fragment, includeClosures: true);
    var inheritance = emitInheritance(fragment);
    var methodAliases = emitInstanceMethodAliases(fragment);
    var tearOffs = emitInstallTearOffs(fragment);
    var constants = emitConstants(fragment);
    var typeRules = emitTypeRules(fragment);
    var variances = emitVariances(fragment);
    var staticNonFinalFields = emitStaticNonFinalFields(fragment);
    var lazyInitializers = emitLazilyInitializedStatics(fragment);
    // TODO(floitsch): only call emitNativeSupport if we need native.
    var nativeSupport = emitNativeSupport(fragment);
    int size = 0;
    if (estimateSize) {
      var estimator = SizeEstimator();
      estimator.visit(classPrototypes);
      estimator.visit(closurePrototypes);
      estimator.visit(inheritance);
      estimator.visit(methodAliases);
      estimator.visit(tearOffs);
      estimator.visit(constants);
      estimator.visit(typeRules);
      estimator.visit(variances);
      estimator.visit(staticNonFinalFields);
      estimator.visit(lazyInitializers);
      estimator.visit(nativeSupport);
      size = estimator.charCount;
    }
    var emittedOutputUnit = EmittedOutputUnit(
        fragment,
        fragment.outputUnit,
        fragment.libraries,
        classPrototypes,
        closurePrototypes,
        inheritance,
        methodAliases,
        tearOffs,
        constants,
        typeRules,
        variances,
        staticNonFinalFields,
        lazyInitializers,
        nativeSupport);
    return PreFragment(fragment.outputFileName, emittedOutputUnit, size);
  }

  js.Statement emitMainFragment(
      Program program,
      Map<String, List<FinalizedFragment>> fragmentsToLoad,
      DeferredLoadingState deferredLoadingState) {
    MainFragment fragment = program.fragments.first;

    // Emit holder code.
    var holderCode = emitHolderCode(fragment.libraries);
    var holderDeclaration = DeferredHolderResource(
        DeferredHolderResourceKind.mainFragment,
        mainResourceName,
        [fragment],
        holderCode);
    js.Statement mainCode = js.js.statement(_mainBoilerplate, {
      // TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
      'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
      'directAccessTestExpression': js.js(_directAccessTestExpression),
      'cyclicThrow': _emitter
          .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
      'throwLateFieldADI': _emitter
          .staticFunctionAccess(_closedWorld.commonElements.throwLateFieldADI),
      'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
      'tearOffCode': js.Block(
          buildTearOffCode(_options, _emitter, _closedWorld.commonElements)),
      'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
      'embeddedInterceptorTags':
          generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
      'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
      'embeddedGlobalsObject': js.js("init"),
      'staticStateDeclaration': DeferredHolderParameter(),
      'staticState': DeferredHolderParameter(),
      'holders': holderDeclaration,
      'startupMetrics': _closedWorld.backendUsage.requiresStartupMetrics,

      // Tearoff parameters:
      'tpContainer': js.string(TearOffParametersPropertyNames.container),
      'tpIsStatic': js.string(TearOffParametersPropertyNames.isStatic),
      'tpIsIntercepted':
          js.string(TearOffParametersPropertyNames.isIntercepted),
      'tpRequiredParameterCount':
          js.string(TearOffParametersPropertyNames.requiredParameterCount),
      'tpOptionalParamaterDefaultValues': js.string(
          TearOffParametersPropertyNames.optionalParameterDefaultValues),
      'tpCallNames': js.string(TearOffParametersPropertyNames.callNames),
      'tpFunctionsOrNames':
          js.string(TearOffParametersPropertyNames.funsOrNames),
      'tpFunctionType': js.string(TearOffParametersPropertyNames.funType),
      'tpApplyIndex': js.string(TearOffParametersPropertyNames.applyIndex),
      'tpNeedsDirectAccess':
          js.string(TearOffParametersPropertyNames.needsDirectAccess),

      //'callName': js.string(_namer.fixedNames.callNameField),
      //'stubName': js.string(_namer.stubNameField),
      //'argumentCount': js.string(_namer.fixedNames.requiredParameterField),
      //'defaultArgumentValues': js.string(_namer.fixedNames.defaultValuesField),
      'deferredGlobal': ModelEmitter.deferredInitializersGlobal,
      'isTrackingAllocations': _options.experimentalTrackAllocations,
      'prototypes': emitPrototypes(fragment),
      'inheritance': emitInheritance(fragment),
      'aliases': emitInstanceMethodAliases(fragment),
      'tearOffs': emitInstallTearOffs(fragment),
      'constants': emitConstants(fragment),
      'staticNonFinalFields': emitStaticNonFinalFields(fragment),
      'lazyStatics': emitLazilyInitializedStatics(fragment),
      'embeddedGlobalsPart1': emitEmbeddedGlobalsPart1(
          program, fragmentsToLoad, deferredLoadingState),
      'embeddedGlobalsPart2':
          emitEmbeddedGlobalsPart2(program, deferredLoadingState),
      'typeRules': emitTypeRules(fragment),
      'sharedStrings': StringReferenceResource(),
      'variances': emitVariances(fragment),
      'sharedTypeRtis': TypeReferenceResource(),
      'nativeSupport': emitNativeSupport(fragment),
      'jsInteropSupport': jsInteropAnalysis.buildJsInteropBootstrap(
              _codegenWorld, _closedWorld.nativeData, _namer) ??
          js.EmptyStatement(),
      'invokeMain': fragment.invokeMain,

      'call0selector': js.quoteName(call0Name),
      'call1selector': js.quoteName(call1Name),
      'call2selector': js.quoteName(call2Name)
    });
    // We assume emitMainFragment will be the last piece of code we emit.
    finalizeCode(mainResourceName, mainCode, holderCode, finalizeHolders: true);
    return mainCode;
  }

  js.Expression emitCodeFragment(CodeFragment fragment) {
    var holderCode = emitHolderCode(fragment.libraries);

    // TODO(sra): How do we tell if [deferredTypes] is empty? It is filled-in
    // later via the program finalizers. So we should defer the decision on the
    // emptiness of the fragment until the finalizers have run.  For now we seem
    // to get away with the fact that type indexes are either (1) main unit or
    // (2) local to the emitted unit, so there is no such thing as a type in a
    // deferred unit that is referenced from another deferred unit.  If we did
    // not emit any functions, then we probably did not use the signature types
    // in the OutputUnit's types, leaving them unused and tree-shaken.

    if (holderCode.isEmpty && fragment.isEmpty) {
      return null;
    }

    var resourceName = fragment.canonicalOutputUnit.name;
    var updateHolders = DeferredHolderResource(
        DeferredHolderResourceKind.deferredFragment,
        resourceName,
        fragment.fragments,
        holderCode);
    js.Expression code = js.js(_deferredBoilerplate, {
      // TODO(floitsch): don't just reference 'init'.
      'embeddedGlobalsObject': js.Parameter('init'),
      'staticState': DeferredHolderParameter(),
      'updateHolders': updateHolders,
      'prototypes': fragment.classPrototypes,
      'closures': fragment.closurePrototypes,
      'inheritance': fragment.inheritance,
      'aliases': fragment.methodAliases,
      'tearOffs': fragment.tearOffs,
      'typeRules': fragment.typeRules,
      'variances': fragment.variances,
      'constants': fragment.constants,
      'staticNonFinalFields': fragment.staticNonFinalFields,
      'lazyStatics': fragment.lazyInitializers,
      'types': fragment.deferredTypes,
      'nativeSupport': fragment.nativeSupport,
      'typesOffset': _namer.typesOffsetName,
      'sharedStrings': StringReferenceResource(),
      'sharedTypeRtis': TypeReferenceResource(),
    });

    if (_options.experimentStartupFunctions) {
      code = js.Parentheses(code);
    }
    finalizeCode(resourceName, code, holderCode);
    return code;
  }

  /// Adds code to a finalizer.
  void addCodeToFinalizer(void Function(js.Node) addCode, js.Node fragmentCode,
      Map<Entity, List<js.Property>> holderCode) {
    addCode(fragmentCode);
    for (var properties in holderCode.values) {
      for (var property in properties) {
        addCode(property);
      }
    }
  }

  /// Finalizes the code for a fragment, and optionally finalizes holders.
  /// Finalizing holders must be the last step of the emitter.
  void finalizeCode(String resourceName, js.Node code,
      Map<Entity, List<js.Property>> holderCode,
      {bool finalizeHolders = false}) {
    StringReferenceFinalizer stringFinalizer =
        StringReferenceFinalizerImpl(_options.enableMinification);
    addCodeToFinalizer(stringFinalizer.addCode, code, holderCode);
    stringFinalizer.finalize();
    TypeReferenceFinalizer typeFinalizer = TypeReferenceFinalizerImpl(
        _emitter, _commonElements, _recipeEncoder, _options.enableMinification);
    addCodeToFinalizer(typeFinalizer.addCode, code, holderCode);
    typeFinalizer.finalize();

    // DeferredHolders need to be finalized last. In addition, finalizing
    // holders needs to be the very last thing the [FragmentEmitter] does before
    // we actually emit code. This is to ensure all holders are registered.
    // Note: Unlike the above finalizers, which are created and finalized
    // per output unit, the holderFinalizer is a whole-program finalizer,
    // which collects deferred [Node]s from each call to `finalizeCode`
    // before begin finalized once for the last (main) unit.
    void _addCode(js.Node code) {
      _holderFinalizer.addCode(resourceName, code);
    }

    addCodeToFinalizer(_addCode, code, holderCode);
    if (finalizeHolders) {
      _holderFinalizer.finalize();
    }
  }

  /// Emits holder code for a list of libraries. We emit [Property]s directly
  /// into a map keyed by [Entity] because we don't yet know anything about the
  /// structure of the underlying holders and thus we cannot emit this code
  /// directly into the ast.
  Map<Entity, List<js.Property>> emitHolderCode(List<Library> libraries) {
    Map<Entity, List<js.Property>> holderCode = {};
    for (Library library in libraries) {
      for (StaticMethod method in library.statics) {
        Map<js.Name, js.Expression> propertyMap = emitStaticMethod(method);
        propertyMap.forEach((js.Name key, js.Expression value) {
          var property = _options.features.legacyJavaScript.isEnabled
              ? js.Property(js.quoteName(key), value)
              : js.MethodDefinition(js.quoteName(key), value);
          Entity holderKey;
          if (method is StaticStubMethod) {
            // [StaticStubMethod]s should only be created for interceptors.
            assert(method.library == _commonElements.interceptorsLibrary);
            holderKey = method.library;
          } else {
            holderKey = method.element;
          }
          (holderCode[holderKey] ??= []).add(property);
          registerEntityAst(method.element, property, library: library.element);
        });
      }
      for (Class cls in library.classes) {
        js.Expression constructor = emitConstructor(cls);
        var property = js.Property(js.quoteName(cls.name), constructor);
        (holderCode[cls.element] ??= []).add(property);
        registerEntityAst(cls.element, property, library: library.element);
      }
    }
    return holderCode;
  }

  /// Emits the given [method].
  ///
  /// A Dart method might result in several JavaScript functions, if it
  /// requires stubs. The returned map contains the original method and all
  /// the stubs it needs.
  Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) {
    Map<js.Name, js.Expression> jsMethods = {};

    // We don't need to install stub-methods. They can only be used when there
    // are tear-offs, in which case they are emitted there.
    assert(() {
      if (method is StaticDartMethod) {
        return method.needsTearOff || method.parameterStubs.isEmpty;
      }
      return true;
    }());
    jsMethods[method.name] = method.code;

    return jsMethods;
  }

  /// Emits a constructor for the given class [cls].
  ///
  /// The constructor is statically built.
  js.Expression emitConstructor(Class cls) {
    js.Name name = cls.name;
    // If the class is not directly instantiated we only need it for inheritance
    // or RTI. In either case we don't need its fields.
    if (cls.isNative || !cls.isDirectlyInstantiated) {
      return js.js('function #() { }', name);
    }

    var statements = <js.Statement>[];
    var parameters = <js.Parameter>[];
    var thisRef;

    if (_options.experimentalTrackAllocations) {
      String qualifiedName =
          "${cls.element.library.canonicalUri}:${cls.element.name}";
      statements.add(js.js.statement('allocations["$qualifiedName"] = true'));
    }

    List<Field> emittedFields = cls.fields.where((f) => !f.isElided).toList();

    // If there are many references to `this`, cache it in a local.
    if (emittedFields.length + (cls.hasRtiField ? 1 : 0) >= 4) {
      // Parameters are named t0, t1, etc, so '_' will not conflict. Forcing '_'
      // in minified mode works because no parameter or local also minifies to
      // '_' (the minifier doesn't know '_' is available).
      js.Name underscore = StringBackedName('_');
      statements.add(js.js.statement('var # = this;', underscore));
      thisRef = underscore;
    } else {
      thisRef = js.js('this');
    }

    // Chain assignments of the same value, e.g. `this.b = this.a = null`.
    // Limit chain length so that the JavaScript parser has bounded recursion.
    const int maxChainLength = 30;
    js.Expression assignment = null;
    int chainLength = 0;
    ConstantValue previousConstant = null;
    void flushAssignment() {
      if (assignment != null) {
        statements.add(js.js.statement('#;', assignment));
        assignment = null;
        chainLength = 0;
        previousConstant = null;
      }
    }

    for (Field field in emittedFields) {
      ConstantValue constant = field.initializerInAllocator;
      if (constant != null) {
        if (constant == previousConstant && chainLength < maxChainLength) {
          assignment = js.js('#.# = #', [thisRef, field.name, assignment]);
        } else {
          flushAssignment();
          assignment = js.js('#.# = #', [
            thisRef,
            field.name,
            _constantEmitter.generate(constant),
          ]);
        }
        ++chainLength;
        previousConstant = constant;
      } else {
        flushAssignment();
        js.Parameter parameter = js.Parameter('t${parameters.length}');
        parameters.add(parameter);
        statements.add(
            js.js.statement('#.# = #', [thisRef, field.name, parameter.name]));
      }
    }
    flushAssignment();

    if (cls.hasRtiField) {
      js.Parameter parameter = js.Parameter('t${parameters.length}');
      parameters.add(parameter);
      statements.add(js.js.statement(
          '#.# = #', [thisRef, _namer.rtiFieldJsName, parameter.name]));
    }

    return js.js('function #(#) { # }', [name, parameters, statements]);
  }

  /// Emits the prototype-section of the fragment.
  ///
  /// This section updates the prototype-property of all constructors in the
  /// global holders.
  ///
  /// If [includeClosures] is `true` only prototypes for closure classes are
  /// generated, if [includeClosures] is `false` only prototypes for non-closure
  /// classes are generated. Otherwise prototypes for all classes are generated.
  js.Statement emitPrototypes(Fragment fragment, {bool includeClosures}) {
    List<js.Statement> assignments = fragment.libraries
        .expand((Library library) => library.classes)
        .where((Class cls) {
      if (includeClosures != null) {
        if (cls.element.isClosure != includeClosures) {
          return false;
        }
      }
      return true;
    }).map((Class cls) {
      var proto = js.js.statement(
          '#.prototype = #;', [classReference(cls), emitPrototype(cls)]);
      ClassEntity element = cls.element;
      registerEntityAst(element, proto, library: element.library);
      return proto;
    }).toList(growable: false);

    return js.Block(assignments);
  }

  /// Emits the prototype of the given class [cls].
  ///
  /// The prototype is generated as object literal. Inheritance is ignored.
  ///
  /// The prototype also includes the `is-property` that every class must have.
  // TODO(floitsch): we could avoid that property if we knew that it wasn't
  //    needed.
  js.Expression emitPrototype(Class cls) {
    Iterable<Method> methods = cls.methods;
    Iterable<Method> checkedSetters = cls.checkedSetters;
    Iterable<Method> isChecks = cls.isChecks;
    Iterable<Method> callStubs = cls.callStubs;
    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
    Iterable<Method> gettersSetters = cls.gettersSetters;
    Iterable<Method> allMethods = [
      ...methods,
      ...checkedSetters,
      ...isChecks,
      ...callStubs,
      ...noSuchMethodStubs,
      ...gettersSetters
    ];

    List<js.Property> properties = [];

    if (cls.superclass == null) {
      // This is Dart `Object`. Add properties that are usually added by
      // `inherit`.

      // TODO(sra): Adding properties here appears to be redundant with the call
      // to `inherit(P.Object, null)` in the generated code. See if we can
      // remove that.

      if (_options.features.legacyJavaScript.isEnabled) {
        // IE11 might require us to set 'constructor' but we aren't 100% sure.
        properties
            .add(js.Property(js.string("constructor"), classReference(cls)));
      }
      properties.add(js.Property(_namer.operatorIs(cls.element), js.number(1)));
    }

    allMethods.forEach((Method method) {
      emitInstanceMethod(method)
          .forEach((js.Expression name, js.Expression code) {
        js.Property property;
        if (_options.features.legacyJavaScript.isEnabled) {
          property = js.Property(name, code);
        } else {
          property = code is js.Fun
              ? js.MethodDefinition(name, code)
              : js.Property(name, code);
        }
        registerEntityAst(method.element, property);
        properties.add(property);
      });
    });

    // Closures have metadata that is often the same. We avoid repeated metadata
    // by putting it on a shared superclass. It is overridden in the subclass if
    // necessary.

    int arity = cls.sharedClosureApplyMetadata;
    if (arity != null) {
      // This is a closure base class that has the specialized `Function.apply`
      // metadata for functions taking exactly [arity] arguments.
      properties.add(js.Property(js.string(_namer.fixedNames.callCatchAllName),
          js.quoteName(callNamesByArity[arity])));
      properties.add(js.Property(
          js.string(_namer.fixedNames.requiredParameterField),
          js.number(arity)));
    }

    if (cls.isClosureBaseClass) {
      // Most closures have no optional arguments.
      properties.add(js.Property(
          js.string(_namer.fixedNames.defaultValuesField), js.LiteralNull()));
    }

    return js.ObjectInitializer(properties);
  }

  /// Emits the given instance [method].
  ///
  /// The given method may be a stub-method (for example for is-checks).
  ///
  /// If it is a Dart-method, all necessary stub-methods are emitted, too. In
  /// that case the returned map contains more than just one entry.
  ///
  /// If the method is a closure call-method, also returns the necessary
  /// properties in case the closure can be applied.
  Map<js.Expression, js.Expression> emitInstanceMethod(Method method) {
    var properties = <js.Expression, js.Expression>{};

    properties[method.name] = method.code;
    if (method is InstanceMethod) {
      for (ParameterStubMethod stubMethod in method.parameterStubs) {
        properties[stubMethod.name] = stubMethod.code;
      }

      if (method.isClosureCallMethod && method.canBeApplied) {
        // The `call` method might flow to `Function.apply`, so the metadata for
        // `Function.apply` is needed.

        // Avoid adding the metadata if a superclass has the same metadata.
        if (!method.inheritsApplyMetadata) {
          js.Name applyName = method.applyIndex == 0
              ? method.name
              : method.parameterStubs[method.applyIndex - 1].name;
          properties[js.string(_namer.fixedNames.callCatchAllName)] =
              js.quoteName(applyName);
          properties[js.string(_namer.fixedNames.requiredParameterField)] =
              js.number(method.requiredParameterCount);

          js.Expression defaultValues =
              _encodeOptionalParameterDefaultValues(method);
          // Default values property of `null` is stored on the common JS
          // superclass.
          if (defaultValues is! js.LiteralNull) {
            properties[js.string(_namer.fixedNames.defaultValuesField)] =
                defaultValues;
          }
        }
      }
    }

    return properties;
  }

  /// Emits the inheritance block of the fragment.
  ///
  /// In this section prototype chains are updated and mixin functions are
  /// copied.
  js.Statement emitInheritance(Fragment fragment) {
    List<js.Statement> inheritCalls = [];
    List<js.Statement> mixinCalls = [];
    // local caches of functions to allow minifaction of function name in call.
    LocalAliases locals = LocalAliases();

    Set<Class> classesInFragment = Set();
    for (Library library in fragment.libraries) {
      classesInFragment.addAll(library.classes);
    }

    Map<Class, List<Class>> subclasses = {};
    Set<Class> seen = Set();

    void collect(cls) {
      if (cls == null || seen.contains(cls)) return;

      Class superclass = cls.superclass;
      if (classesInFragment.contains(superclass)) {
        collect(superclass);
      }

      subclasses.putIfAbsent(superclass, () => []).add(cls);

      seen.add(cls);
    }

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        collect(cls);
        if (cls.mixinClass != null) {
          js.Statement statement = js.js.statement('#(#, #)', [
            locals.find('_mixin', 'hunkHelpers.mixin'),
            classReference(cls),
            classReference(cls.mixinClass),
          ]);
          registerEntityAst(cls.element, statement, library: library.element);
          mixinCalls.add(statement);
        }
      }
    }

    for (Class superclass in subclasses.keys) {
      List<Class> list = subclasses[superclass];
      js.Expression superclassReference =
          (superclass == null) ? js.LiteralNull() : classReference(superclass);
      if (list.length == 1) {
        Class cls = list.single;
        var statement = js.js.statement('#(#, #)', [
          locals.find('_inherit', 'hunkHelpers.inherit'),
          classReference(cls),
          superclassReference
        ]);
        registerEntityAst(cls.element, statement, library: cls.element.library);
        inheritCalls.add(statement);
      } else {
        List<js.Expression> listElements = [];
        // Since inheritMany shares the superclass reference, we attribute it
        // only to the first subclass.
        ClassEntity firstClass = list.first.element;
        registerEntityAst(firstClass, superclassReference,
            library: firstClass.library);
        for (Class cls in list) {
          js.Expression reference = classReference(cls);
          registerEntityAst(cls.element, reference,
              library: cls.element.library);
          listElements.add(reference);
        }
        inheritCalls.add(js.js.statement('#(#, #)', [
          locals.find('_inheritMany', 'hunkHelpers.inheritMany'),
          superclassReference,
          js.ArrayInitializer(listElements)
        ]));
      }
    }

    List<js.Statement> statements = [];
    if (locals.isNotEmpty) {
      statements.add(locals.toStatement());
    }
    statements.addAll(inheritCalls);
    statements.addAll(mixinCalls);
    return wrapPhase('inheritance', statements);
  }

  /// Emits the setup of method aliases.
  ///
  /// This step consists of simply copying JavaScript functions to their
  /// aliased names so they point to the same function.
  js.Statement emitInstanceMethodAliases(Fragment fragment) {
    List<js.Statement> assignments = [];

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        bool firstAlias = true;
        for (InstanceMethod method in cls.methods) {
          if (method.aliasName != null) {
            if (firstAlias) {
              firstAlias = false;
              js.Statement statement = js.js.statement(
                  assignments.isEmpty
                      ? 'var _ = #.prototype;'
                      : '_ = #.prototype',
                  classReference(cls));
              registerEntityAst(method.element, statement);
              assignments.add(statement);
            }
            js.Statement statement = js.js.statement('_.# = _.#',
                [js.quoteName(method.aliasName), js.quoteName(method.name)]);
            registerEntityAst(method.element, statement);
            assignments.add(statement);
          }
        }
      }
    }
    return wrapPhase('aliases', assignments);
  }

  /// Encodes the optional default values so that the runtime Function.apply
  /// can use them.
  js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
    // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
    if (method.optionalParameterDefaultValues is List) {
      List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
      if (defaultValues.isEmpty) {
        return js.LiteralNull();
      }
      Iterable<js.Expression> elements =
          defaultValues.map(generateConstantReference);
      return js.js(
          'function() { return #; }', js.ArrayInitializer(elements.toList()));
    } else {
      Map<String, ConstantValue> defaultValues =
          method.optionalParameterDefaultValues;
      List<js.Property> properties = [];
      List<String> names = defaultValues.keys.toList(growable: false);
      // Sort the names the same way we sort them for the named-argument calling
      // convention.
      names.sort();

      for (String name in names) {
        ConstantValue value = defaultValues[name];
        properties.add(
            js.Property(js.string(name), generateConstantReference(value)));
      }
      return js.js(
          'function() { return #; }', js.ObjectInitializer(properties));
    }
  }

  /// Wraps the statement in a named function to that it shows up as a unit in
  /// profiles.
  // TODO(sra): Should this be conditional?
  js.Statement wrapPhase(String name, List<js.Statement> statements) {
    js.Block block = js.Block(statements);
    if (statements.isEmpty) return block;
    return js.js.statement('(function #(){#})();', [name, block]);
  }

  /// Emits the section that installs tear-off getters.
  js.Statement emitInstallTearOffs(Fragment fragment) {
    LocalAliases locals = LocalAliases();

    /// Emits the statement that installs a tear off for a method.
    ///
    /// Tear-offs might be passed to `Function.apply` which means that all
    /// calling-conventions (with or without optional positional/named
    /// arguments) are possible. As such, the tear-off needs enough information
    /// to fill in missing parameters.
    js.Statement emitInstallTearOff(
        js.Expression container, DartMethod method) {
      List<js.Name> callNames = [];
      List<js.Expression> funsOrNames = [];

      /// Adds the stub-method's code or name to the [funsOrNames] array.
      ///
      /// Static methods don't need stub-methods except for tear-offs. As such,
      /// they are not emitted in the prototype, but directly passed here.
      ///
      /// Instance-methods install the stub-methods in their prototype, and we
      /// use string-based redirections to find them there.
      void addFunOrName(StubMethod stubMethod) {
        if (method.isStatic) {
          funsOrNames.add(stubMethod.code);
        } else {
          funsOrNames.add(js.quoteName(stubMethod.name));
        }
      }

      callNames.add(method.callName);
      // The first entry in the funsOrNames-array must be a string.
      funsOrNames.add(js.quoteName(method.name));
      for (ParameterStubMethod stubMethod in method.parameterStubs) {
        js.Name callName = stubMethod.callName;
        // `callName` might be `null` if the method is called directly with some
        // CallStructure but it can be proven that the tearoff not called with
        // with that CallStructure, e.g. the closure does no need the defaulting
        // of arguments but some direct call does.
        if (callName != null) {
          callNames.add(callName);
          addFunOrName(stubMethod);
        }
      }

      final callNameArray =
          js.ArrayInitializer([...callNames.map(js.quoteName)]);
      final funsOrNamesArray = js.ArrayInitializer(funsOrNames);

      bool isIntercepted = false;
      if (method is InstanceMethod) {
        isIntercepted = method.isIntercepted;
      }

      int requiredParameterCount = method.requiredParameterCount;
      js.Expression optionalParameterDefaultValues = js.LiteralNull();
      if (method.canBeApplied) {
        optionalParameterDefaultValues =
            _encodeOptionalParameterDefaultValues(method);
      }

      var applyIndex = js.number(method.applyIndex);

      if (method.isStatic) {
        if (requiredParameterCount <= 2 &&
            callNames.length == 1 &&
            optionalParameterDefaultValues is js.LiteralNull &&
            method.applyIndex == 0) {
          js.Statement finish(int arity) {
            // Short form for exactly 0/1/2 arguments.
            var install =
                locals.find('_static_${arity}', 'hunkHelpers._static_${arity}');
            return js.js.statement('''
                #install(#container, #getterName, #name, #funType)''', {
              "install": install,
              "container": container,
              "getterName": js.quoteName(method.tearOffName),
              "name": funsOrNames.single,
              "funType": method.functionType,
            });
          }

          var installedName = callNames.single;
          if (installedName == call0Name) return finish(0);
          if (installedName == call1Name) return finish(1);
          if (installedName == call2Name) return finish(2);
        }

        var install =
            locals.find('_static', 'hunkHelpers.installStaticTearOff');
        return js.js.statement('''
            #install(#container, #getterName,
                     #requiredParameterCount, #optionalParameterDefaultValues,
                      #callNames, #funsOrNames, #funType, #applyIndex)''', {
          "install": install,
          "container": container,
          "getterName": js.quoteName(method.tearOffName),
          "requiredParameterCount": js.number(requiredParameterCount),
          "optionalParameterDefaultValues": optionalParameterDefaultValues,
          "callNames": callNameArray,
          "funsOrNames": funsOrNamesArray,
          "funType": method.functionType,
          "applyIndex": applyIndex,
        });
      } else {
        bool tearOffNeedsDirectAccess =
            (method as InstanceMethod).tearOffNeedsDirectAccess;
        if (requiredParameterCount <= 2 &&
            callNames.length == 1 &&
            optionalParameterDefaultValues is js.LiteralNull &&
            method.applyIndex == 0 &&
            !tearOffNeedsDirectAccess) {
          js.Statement finish(int arity) {
            // Short form for exactly 0/1/2 arguments.
            String isInterceptedTag = isIntercepted ? 'i' : 'u';
            var install = locals.find('_instance_${arity}_${isInterceptedTag}',
                'hunkHelpers._instance_${arity}${isInterceptedTag}');
            return js.js.statement('''
                #install(#container, #getterName, #name, #funType)''', {
              "install": install,
              "container": container,
              "getterName": js.quoteName(method.tearOffName),
              "name": funsOrNames.single,
              "funType": method.functionType,
            });
          }

          var installedName = callNames.single;
          if (installedName == call0Name) return finish(0);
          if (installedName == call1Name) return finish(1);
          if (installedName == call2Name) return finish(2);
        }

        var install =
            locals.find('_instance', 'hunkHelpers.installInstanceTearOff');
        return js.js.statement('''
            #install(#container, #getterName, #isIntercepted,
                     #requiredParameterCount, #optionalParameterDefaultValues,
                     #callNames, #funsOrNames, #funType, #applyIndex,
                     #tearOffNeedsDirectAccess)''', {
          "install": install,
          "container": container,
          "getterName": js.quoteName(method.tearOffName),
          // 'Truthy' values are ok for `isIntercepted`.
          "isIntercepted": js.number(isIntercepted ? 1 : 0),
          "requiredParameterCount": js.number(requiredParameterCount),
          "optionalParameterDefaultValues": optionalParameterDefaultValues,
          "callNames": callNameArray,
          "funsOrNames": funsOrNamesArray,
          "funType": method.functionType,
          "applyIndex": applyIndex,
          // 'Truthy' values are ok for `tearOffNeedsDirectAccess`.
          "tearOffNeedsDirectAccess":
              js.number(tearOffNeedsDirectAccess ? 1 : 0),
        });
      }
    }

    List<js.Statement> inits = [];
    js.Expression temp;

    for (Library library in fragment.libraries) {
      for (StaticMethod method in library.statics) {
        // TODO(floitsch): can there be anything else than a StaticDartMethod?
        if (method is StaticDartMethod) {
          if (method.needsTearOff) {
            js.Statement statement = emitInstallTearOff(
                _namer.readGlobalObjectForMember(method.element), method);
            registerEntityAst(method.element, statement,
                library: library.element);
            inits.add(statement);
          }
        }
      }
      for (Class cls in library.classes) {
        var methods = cls.methods.where((dynamic m) => m.needsTearOff).toList();
        js.Expression container = js.js("#.prototype", classReference(cls));
        js.Expression reference = container;
        if (methods.length > 1) {
          if (temp == null) {
            inits.add(js.js.statement('var _;'));
            temp = js.js('_');
          }
          // First call uses assignment to temp to cache the container.
          reference = js.js('# = #', [temp, container]);
        }
        for (InstanceMethod method in methods) {
          js.Statement statement = emitInstallTearOff(reference, method);
          registerEntityAst(method.element, statement);
          inits.add(statement);
          reference = temp; // Second and subsequent calls use temp.
        }
      }
    }

    if (locals.isNotEmpty) {
      inits.insert(0, locals.toStatement());
    }

    return wrapPhase('installTearOffs', inits);
  }

  /// Emits the constants section.
  js.Statement emitConstants(Fragment fragment) {
    List<js.Statement> assignments = [];
    bool hasList = false;
    for (Constant constant in fragment.constants) {
      // TODO(25230): We only need to name constants that are used from function
      // bodies or from other constants in a different part.
      var assignment = js.js.statement('#.# = #', [
        _namer.globalObjectForConstant(constant.value),
        constant.name,
        _constantEmitter.generate(constant.value)
      ]);
      _dumpInfoTask.registerConstantAst(constant.value, assignment);
      assignments.add(assignment);
      if (constant.value.isList) hasList = true;
    }
    if (hasList) {
      assignments.insert(
          0, js.js.statement('var makeConstList = hunkHelpers.makeConstList;'));
    }
    return wrapPhase('constants', assignments);
  }

  /// Emits the static non-final fields section.
  ///
  /// This section initializes all static non-final fields that don't require
  /// an initializer.
  js.Statement emitStaticNonFinalFields(Fragment fragment) {
    List<StaticField> fields = fragment.staticNonFinalFields;
    // TODO(sra): Chain assignments that have the same value, i.e.
    //
    //    $.x = null; $.y = null; $.z = null;
    // -->
    //    $.z = $.y = $.x = null;
    //
    Iterable<js.Statement> statements = fields.map((StaticField field) {
      // TODO(joshualitt): Distribute fields into per-unit holders and use a
      // deferred holder expression for the field assignment left-hand-side.
      js.Expression location =
          js.js('#.#', [_namer.globalObjectForStaticState(), field.name]);
      js.Statement statement;
      if (field.isInitializedByConstant) {
        statement = js.js.statement("# = #;", [location, field.code]);
      } else {
        // This is a bit of a hack. Field initializers are generated as a
        // function ending with a return statement. We replace the function
        // with the body block and replace the return statement with an
        // assignment to the field.
        //
        // Since unneeded blocks are not generated in the output,
        // the statement(s) of the initializes are inlined in the emitted code.
        //
        // This is a cheap way of supporting eager fields (as opposed to
        // generating one SSA graph for all eager fields) though it does not
        // avoid redundant declaration of local variable, for instance for
        // type arguments.
        js.Fun code = field.code;
        assert(code != null, "No code for $field");
        if (code.params.isEmpty &&
            code.body.statements.length == 1 &&
            code.body.statements.last is js.Return) {
          // For now we only support initializers of the form
          //
          //   function() { return e; }
          //
          // To avoid unforeseen consequences of having parameters and locals
          // in the initializer code.
          js.Return last = code.body.statements.last;
          statement = js.js.statement("# = #;", [location, last.value]);
        } else {
          // Safe fallback in the event of a field initializer with no return
          // statement as the last statement.
          statement = js.js.statement("# = #();", [location, code]);
        }
      }
      registerEntityAst(field.element, statement,
          library: field.element.library);
      return statement;
    });
    return wrapPhase('staticFields', statements.toList());
  }

  /// Emits lazy fields.
  ///
  /// This section initializes all static (final and non-final) fields that
  /// require an initializer.
  js.Statement emitLazilyInitializedStatics(Fragment fragment) {
    List<StaticField> fields = fragment.staticLazilyInitializedFields;
    List<js.Statement> statements = [];
    LocalAliases locals = LocalAliases();
    for (StaticField field in fields) {
      String helper = field.usesNonNullableInitialization
          ? field.isFinal
              ? locals.find('_lazyFinal', 'hunkHelpers.lazyFinal')
              : locals.find('_lazy', 'hunkHelpers.lazy')
          : locals.find('_lazyOld', 'hunkHelpers.lazyOld');
      js.Statement statement = js.js.statement("#(#, #, #, #);", [
        helper,
        _namer.globalObjectForStaticState(),
        js.quoteName(field.name),
        js.quoteName(field.getterName),
        field.code,
      ]);

      registerEntityAst(field.element, statement,
          library: field.element.library);
      statements.add(statement);
    }

    if (locals.isNotEmpty) {
      statements.insert(0, locals.toStatement());
    }

    return wrapPhase('lazyInitializers', statements);
  }

  /// Emits the embedded globals that are needed for deferred loading.
  ///
  /// This function is only invoked for the main fragment.
  ///
  /// The [loadMap] contains a map from load-ids (for each deferred library)
  /// to the list of generated fragments that must be installed when the
  /// deferred library is loaded.
  Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
      DeferredLoadingState deferredLoadingState) {
    List<js.Property> globals = [];

    globals.add(js.Property(
        js.string(DEFERRED_INITIALIZED), js.js("Object.create(null)")));

    String deferredGlobal = ModelEmitter.deferredInitializersGlobal;
    js.Expression isHunkLoadedFunction =
        js.js("function(hash) { return !!$deferredGlobal[hash]; }");
    globals.add(js.Property(js.string(IS_HUNK_LOADED), isHunkLoadedFunction));

    js.Expression isHunkInitializedFunction = js.js(
        "function(hash) { return !!#deferredInitialized[hash]; }", {
      'deferredInitialized': generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)
    });
    globals.add(
        js.Property(js.string(IS_HUNK_INITIALIZED), isHunkInitializedFunction));

    /// See [finalizeDeferredLoadingData] for the format of the deferred hunk.
    js.Expression initializeLoadedHunkFunction = js.js("""
            function(hash) {
              var hunk = $deferredGlobal[hash];
              if (hunk == null) {
                throw "DeferredLoading state error: code with hash '" +
                    hash + "' was not loaded";
              }
              initializeDeferredHunk(hunk);
              #deferredInitialized[hash] = true;
            }""", {
      'deferredInitialized': generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)
    });

    globals.add(js.Property(
        js.string(INITIALIZE_LOADED_HUNK), initializeLoadedHunkFunction));

    globals.add(js.Property(js.string(DEFERRED_LIBRARY_PARTS),
        deferredLoadingState.deferredLibraryParts));
    globals.add(js.Property(
        js.string(DEFERRED_PART_URIS), deferredLoadingState.deferredPartUris));
    globals.add(js.Property(js.string(DEFERRED_PART_HASHES),
        deferredLoadingState.deferredPartHashes));

    return globals;
  }

  // Create data used for loading and initializing the hunks for a deferred
  // import. There are three parts: a map from loadId to list of parts, where
  // parts are represented as an index; an array of uris indexed by part; and an
  // array of hashes indexed by part.
  // [deferredLoadHashes] may have missing entries to indicate empty parts.
  void finalizeDeferredLoadingData(
      Map<String, List<CodeFragment>> codeFragmentsToLoad,
      Map<CodeFragment, FinalizedFragment> codeFragmentMap,
      Map<CodeFragment, String> deferredLoadHashes,
      DeferredLoadingState deferredLoadingState) {
    if (codeFragmentsToLoad.isEmpty) return;

    // We store a map of indices to uris and hashes. Because multiple
    // [CodeFragments] can map to a single file, a uri may appear multiple times
    // in [fragmentUris] once per [CodeFragment] reference in that file.
    // TODO(joshualitt): Use a string table to avoid duplicating part file
    // names.
    Map<CodeFragment, int> fragmentIndexes = {};
    List<String> fragmentUris = [];
    List<String> fragmentHashes = [];

    List<js.Property> libraryPartsMapEntries = [];

    codeFragmentsToLoad
        .forEach((String loadId, List<CodeFragment> codeFragments) {
      List<js.Expression> indexes = [];
      for (var codeFragment in codeFragments) {
        var fragment = codeFragmentMap[codeFragment];
        String codeFragmentHash = deferredLoadHashes[codeFragment];
        if (codeFragmentHash == null) continue;
        int index = fragmentIndexes[codeFragment];
        if (index == null) {
          index = fragmentIndexes[codeFragment] = fragmentIndexes.length;
          fragmentUris.add(
              "${fragment.outputFileName}.${ModelEmitter.deferredExtension}");
          fragmentHashes.add(codeFragmentHash);
        }
        indexes.add(js.number(index));
      }
      libraryPartsMapEntries
          .add(js.Property(js.string(loadId), js.ArrayInitializer(indexes)));
    });

    deferredLoadingState.deferredLibraryParts.setValue(
        js.ObjectInitializer(libraryPartsMapEntries, isOneLiner: false));
    deferredLoadingState.deferredPartUris
        .setValue(js.stringArray(fragmentUris));
    deferredLoadingState.deferredPartHashes
        .setValue(js.stringArray(fragmentHashes));
  }

  /// Emits the [MANGLED_GLOBAL_NAMES] embedded global.
  ///
  /// This global maps minified names for selected classes (some important
  /// core classes, and some native classes) to their unminified names.
  js.Property emitMangledGlobalNames() {
    List<js.Property> names = [];

    CommonElements commonElements = _closedWorld.commonElements;
    // We want to keep the original names for the most common core classes when
    // calling toString on them.
    List<ClassEntity> nativeClassesNeedingUnmangledName = [
      commonElements.intClass,
      commonElements.doubleClass,
      commonElements.numClass,
      commonElements.stringClass,
      commonElements.boolClass,
      commonElements.nullClass,
      commonElements.listClass
    ];
    // TODO(floitsch): this should probably be on a per-fragment basis.
    nativeClassesNeedingUnmangledName.forEach((element) {
      names.add(js.Property(
          js.quoteName(_namer.className(element)), js.string(element.name)));
    });

    return js.Property(
        js.string(MANGLED_GLOBAL_NAMES), js.ObjectInitializer(names));
  }

  /// Emits the [METADATA] embedded global.
  ///
  /// The metadata itself has already been computed earlier and is stored in
  /// the [program].
  List<js.Property> emitMetadata(Program program) {
    List<js.Property> metadataGlobals = [];

    js.Property createGlobal(js.Expression metadata, String global) {
      return js.Property(js.string(global), metadata);
    }

    var mainUnit = program.mainFragment.outputUnit;
    js.Expression types = program.metadataTypesForOutputUnit(mainUnit);
    metadataGlobals.add(createGlobal(types, TYPES));

    return metadataGlobals;
  }

  /// Emits all embedded globals.
  js.Statement emitEmbeddedGlobalsPart1(
      Program program,
      Map<String, List<FinalizedFragment>> fragmentsToLoad,
      DeferredLoadingState deferredLoadingState) {
    List<js.Property> globals = [];

    if (fragmentsToLoad.isNotEmpty) {
      globals
          .addAll(emitEmbeddedGlobalsForDeferredLoading(deferredLoadingState));
    }

    if (program.typeToInterceptorMap != null) {
      // This property is assigned later.
      // Initialize property to avoid map transitions.
      globals.add(
          js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP), js.LiteralNull()));
    }

    globals.add(js.Property(js.string(RTI_UNIVERSE), createRtiUniverse()));

    globals.add(emitMangledGlobalNames());

    // The [MANGLED_NAMES] table must contain the mapping for const symbols.
    // Without const symbols, the table is only relevant for reflection and
    // therefore unused in this emitter.
    // TODO(johnniwinther): Remove the need for adding an empty list of
    // mangled names.
    globals
        .add(js.Property(js.string(MANGLED_NAMES), js.ObjectInitializer([])));

    globals.addAll(emitMetadata(program));

    if (program.needsNativeSupport) {
      globals
          .add(js.Property(js.string(INTERCEPTORS_BY_TAG), js.LiteralNull()));
      globals.add(js.Property(js.string(LEAF_TAGS), js.LiteralNull()));
    }

    globals.add(js.Property(
        js.string(ARRAY_RTI_PROPERTY),
        _options.features.legacyJavaScript.isEnabled
            ? js.js(
                r'typeof Symbol == "function" && typeof Symbol() == "symbol"'
                r'    ? Symbol("$ti")'
                r'    : "$ti"')
            : js.js(r'Symbol("$ti")')));

    if (_closedWorld.backendUsage.requiresStartupMetrics) {
      // Copy the metrics object that was stored on the main unit IIFE.
      globals.add(js.Property(
          js.string(STARTUP_METRICS), js.js('dartProgram.$STARTUP_METRICS')));
    }

    js.ObjectInitializer globalsObject =
        js.ObjectInitializer(globals, isOneLiner: false);

    return js.js.statement('var init = #;', globalsObject);
  }

  /// Finish setting up embedded globals.
  js.Statement emitEmbeddedGlobalsPart2(
      Program program, DeferredLoadingState deferredLoadingState) {
    List<js.Statement> statements = [];
    if (program.typeToInterceptorMap != null) {
      statements.add(js.js.statement('init.# = #;',
          [js.string(TYPE_TO_INTERCEPTOR_MAP), program.typeToInterceptorMap]));
    }
    return js.Block(statements);
  }

  js.Block emitTypeRules(Fragment fragment) {
    List<js.Statement> statements = [];

    ClassEntity jsObjectClass = _commonElements.jsJavaScriptObjectClass;

    Map<ClassTypeData, List<ClassTypeData>> nativeRedirections =
        _nativeEmitter.typeRedirections;

    Ruleset ruleset = Ruleset.empty();
    Map<ClassEntity, int> erasedTypes = {};
    Iterable<ClassTypeData> classTypeData =
        fragment.libraries.expand((Library library) => library.classTypeData);
    classTypeData.forEach((ClassTypeData typeData) {
      ClassEntity element = typeData.element;
      InterfaceType targetType = _elementEnvironment.getThisType(element);

      // TODO(fishythefish): Prune uninstantiated classes.
      if (_rtiNeed.classHasErasedTypeArguments(element)) {
        erasedTypes[element] = targetType.typeArguments.length;
      }

      bool isInterop = _classHierarchy.isSubclassOf(element, jsObjectClass);

      if (isInterop && element != jsObjectClass) {
        ruleset.addRedirection(element, jsObjectClass);
      } else {
        Iterable<TypeCheck> checks = typeData.classChecks?.checks ?? const [];
        Iterable<InterfaceType> supertypes = isInterop
            ? checks
                .map((check) => _elementEnvironment.getJsInteropType(check.cls))
            : checks
                .map((check) => _dartTypes.asInstanceOf(targetType, check.cls));

        Map<TypeVariableType, DartType> typeVariables = {};
        Set<TypeVariableType> namedTypeVariables = typeData.namedTypeVariables;
        nativeRedirections[typeData]?.forEach((ClassTypeData redirectee) {
          namedTypeVariables.addAll(redirectee.namedTypeVariables);
        });
        for (TypeVariableType typeVariable in typeData.namedTypeVariables) {
          TypeVariableEntity element = typeVariable.element;
          InterfaceType supertype = isInterop
              ? _elementEnvironment.getJsInteropType(element.typeDeclaration)
              : _dartTypes.asInstanceOf(targetType, element.typeDeclaration);
          List<DartType> supertypeArguments = supertype.typeArguments;
          typeVariables[typeVariable] = supertypeArguments[element.index];
        }
        ruleset.addEntry(targetType, supertypes, typeVariables);
      }
    });

    // We add native redirections only to the main fragment in order to avoid
    // duplicating them in multiple deferred units.
    if (fragment.outputUnit.isMainOutput) {
      nativeRedirections
          .forEach((ClassTypeData target, List<ClassTypeData> redirectees) {
        for (ClassTypeData redirectee in redirectees) {
          ruleset.addRedirection(redirectee.element, target.element);
        }
      });
    }

    if (ruleset.isNotEmpty) {
      FunctionEntity addRules = _closedWorld.commonElements.rtiAddRulesMethod;
      statements.add(js.js.statement('#(init.#,JSON.parse(#));', [
        _emitter.staticFunctionAccess(addRules),
        RTI_UNIVERSE,
        _rulesetEncoder.encodeRuleset(ruleset),
      ]));
    }

    if (erasedTypes.isNotEmpty) {
      FunctionEntity addErasedTypes =
          _closedWorld.commonElements.rtiAddErasedTypesMethod;
      statements.add(js.js.statement('#(init.#,JSON.parse(#));', [
        _emitter.staticFunctionAccess(addErasedTypes),
        RTI_UNIVERSE,
        _rulesetEncoder.encodeErasedTypes(erasedTypes),
      ]));
    }

    return js.Block(statements);
  }

  js.Statement emitVariances(Fragment fragment) {
    if (!_options.enableVariance) {
      return js.EmptyStatement();
    }

    Map<ClassEntity, List<Variance>> typeParameterVariances = {};
    Iterable<Class> classes =
        fragment.libraries.expand((Library library) => library.classes);
    classes.forEach((Class cls) {
      ClassEntity element = cls.element;
      List<Variance> classVariances =
          _elementEnvironment.getTypeVariableVariances(element);

      // Emit variances for a class only if there is at least one explicit
      // variance defined.
      bool hasOnlyLegacyVariance = classVariances
          .every((variance) => variance == Variance.legacyCovariant);
      if (!hasOnlyLegacyVariance) {
        typeParameterVariances[element] = classVariances;
      }
    });

    if (typeParameterVariances.isNotEmpty) {
      FunctionEntity addVariances =
          _closedWorld.commonElements.rtiAddTypeParameterVariancesMethod;
      return js.js.statement('#(init.#,JSON.parse(#));', [
        _emitter.staticFunctionAccess(addVariances),
        RTI_UNIVERSE,
        _rulesetEncoder.encodeTypeParameterVariances(typeParameterVariances),
      ]);
    }

    return js.EmptyStatement();
  }

  /// Returns an expression that creates the initial Rti Universe.
  ///
  /// This needs to be kept in sync with `_Universe.create` in `dart:_rti`.
  js.Expression createRtiUniverse() {
    List<js.Property> universeFields = [];
    void initField(String name, String value) {
      universeFields.add(js.Property(js.string(name), js.js(value)));
    }

    initField(RtiUniverseFieldNames.evalCache, 'new Map()');
    initField(RtiUniverseFieldNames.typeRules, '{}');
    initField(RtiUniverseFieldNames.erasedTypes, '{}');
    initField(RtiUniverseFieldNames.typeParameterVariances, '{}');
    initField(RtiUniverseFieldNames.sharedEmptyArray, '[]');

    return js.ObjectInitializer(universeFields);
  }

  /// Emits data needed for native classes.
  js.Statement emitNativeSupport(Fragment fragment) {
    List<js.Statement> statements = [];

    // The isolate-affinity tag must only be initialized once per program.
    if (fragment.isMainFragment &&
        NativeGenerator.needsIsolateAffinityTagInitialization(
            _closedWorld.backendUsage)) {
      statements.add(NativeGenerator.generateIsolateAffinityTagInitialization(
          _closedWorld.backendUsage, generateEmbeddedGlobalAccess, js.js("""
        // On V8, the 'intern' function converts a string to a symbol, which
        // makes property access much faster.
        // TODO(sra): Use Symbol on non-IE11 browsers.
        function (s) {
          var o = {};
          o[s] = 1;
          return Object.keys(hunkHelpers.convertToFastObject(o))[0];
        }""", [])));
    }

    Map<String, js.Expression> interceptorsByTag = {};
    Map<String, js.Expression> leafTags = {};
    List<js.Statement> subclassAssignments = [];

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        if (cls.nativeLeafTags != null) {
          for (String tag in cls.nativeLeafTags) {
            interceptorsByTag[tag] = classReference(cls);
            leafTags[tag] = js.LiteralBool(true);
          }
        }
        if (cls.nativeNonLeafTags != null) {
          for (String tag in cls.nativeNonLeafTags) {
            interceptorsByTag[tag] = classReference(cls);
            leafTags[tag] = js.LiteralBool(false);
          }
          if (cls.nativeExtensions != null) {
            List<Class> subclasses = cls.nativeExtensions;
            js.Expression base = js.string(cls.nativeNonLeafTags[0]);

            for (Class subclass in subclasses) {
              subclassAssignments.add(js.js.statement('#.# = #;', [
                classReference(subclass),
                NATIVE_SUPERCLASS_TAG_NAME,
                base
              ]));
            }
          }
        }
      }
    }

    // Emit the empty objects for main fragment in case we emit
    // getNativeInterceptor.
    // TODO(sra): Refine the impacts to accuratley predict whether we need this
    // at all, and delete 'setOrUpdateInterceptorsByTag' if it is not called.
    if (fragment.isMainFragment || interceptorsByTag.isNotEmpty) {
      statements.add(js.js.statement(
          "hunkHelpers.setOrUpdateInterceptorsByTag(#);",
          js.objectLiteral(interceptorsByTag)));
    }
    if (fragment.isMainFragment || leafTags.isNotEmpty) {
      statements.add(js.js.statement(
          "hunkHelpers.setOrUpdateLeafTags(#);", js.objectLiteral(leafTags)));
    }
    statements.addAll(subclassAssignments);

    return wrapPhase('nativeSupport', statements);
  }
}

class LocalAliases {
  final Map<String, js.Expression> _locals = {};

  bool get isEmpty => _locals.isEmpty;
  bool get isNotEmpty => !isEmpty;

  String find(String alias, String expression) {
    _locals[alias] ??= js.js(expression);
    return alias;
  }

  js.Statement toStatement() {
    List<js.VariableInitialization> initializations = [];
    _locals.forEach((local, value) {
      initializations
          .add(js.VariableInitialization(js.VariableDeclaration(local), value));
    });
    return js.ExpressionStatement(js.VariableDeclarationList(initializations));
  }
}

class DeferredLoadingState {
  final deferredLibraryParts = DeferredPrimaryExpression();
  final deferredPartUris = DeferredPrimaryExpression();
  final deferredPartHashes = DeferredPrimaryExpression();
}

class DeferredPrimaryExpression extends js.DeferredExpression {
  js.Expression _value;

  void setValue(js.Expression value) {
    assert(_value == null);
    assert(value.precedenceLevel == this.precedenceLevel);
    _value = value;
  }

  @override
  js.Expression get value {
    assert(_value != null);
    return _value;
  }

  @override
  int get precedenceLevel => js_precedence.PRIMARY;
}
