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

library dart2js.js_emitter.full_emitter;

import 'dart:collection' show HashMap;
import 'dart:convert';

import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
import 'package:js_runtime/shared/embedded_names.dart'
    show JsBuiltin, JsGetName;

import '../../common.dart';
import '../../common/names.dart' show Names;
import '../../compiler.dart' show Compiler;
import '../../constants/values.dart';
import '../../core_types.dart' show CoreClasses;
import '../../dart_types.dart' show DartType;
import '../../deferred_load.dart' show OutputUnit;
import '../../elements/elements.dart'
    show
        ClassElement,
        Element,
        Elements,
        FieldElement,
        FunctionElement,
        FunctionSignature,
        LibraryElement,
        MetadataAnnotation,
        MethodElement,
        Name,
        TypedefElement,
        VariableElement;
import '../../hash/sha1.dart' show Hasher;
import '../../io/code_output.dart';
import '../../io/line_column_provider.dart'
    show LineColumnCollector, LineColumnProvider;
import '../../io/source_map_builder.dart' show SourceMapBuilder;
import '../../js/js.dart' as jsAst;
import '../../js/js.dart' show js;
import '../../js_backend/backend_helpers.dart' show BackendHelpers;
import '../../js_backend/js_backend.dart'
    show
        CompoundName,
        ConstantEmitter,
        GetterName,
        JavaScriptBackend,
        JavaScriptConstantCompiler,
        Namer,
        SetterName,
        TypeVariableHandler;
import '../../universe/call_structure.dart' show CallStructure;
import '../../universe/selector.dart' show Selector;
import '../../util/characters.dart' show $$, $A, $HASH, $Z, $a, $z;
import '../../util/uri_extras.dart' show relativize;
import '../../util/util.dart' show equalElements;
import '../constant_ordering.dart' show deepCompareConstants;
import '../headers.dart';
import '../js_emitter.dart' hide Emitter;
import '../js_emitter.dart' as js_emitter show Emitter;
import '../model.dart';
import '../program_builder/program_builder.dart';

part 'class_builder.dart';
part 'class_emitter.dart';
part 'code_emitter_helper.dart';
part 'container_builder.dart';
part 'declarations.dart';
part 'deferred_output_unit_hash.dart';
part 'interceptor_emitter.dart';
part 'nsm_emitter.dart';
part 'setup_program_builder.dart';

class Emitter implements js_emitter.Emitter {
  final Compiler compiler;
  final CodeEmitterTask task;

  // The following fields will be set to copies of the program-builder's
  // collector.
  Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists;
  Map<OutputUnit, Set<LibraryElement>> outputLibraryLists;
  List<TypedefElement> typedefsNeededForReflection;

  final ContainerBuilder containerBuilder = new ContainerBuilder();
  final ClassEmitter classEmitter = new ClassEmitter();
  final NsmEmitter nsmEmitter = new NsmEmitter();
  final InterceptorEmitter interceptorEmitter = new InterceptorEmitter();

  // TODO(johnniwinther): Wrap these fields in a caching strategy.
  final Set<ConstantValue> cachedEmittedConstants;
  final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[];
  final Map<Element, ClassBuilder> cachedClassBuilders;
  final Set<Element> cachedElements;

  bool needsClassSupport = false;
  bool needsMixinSupport = false;
  bool needsLazyInitializer = false;

  /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info",
  /// that is, some function was needed for reflection, had stubs, or had a
  /// super alias.
  bool needsStructuredMemberInfo = false;

  final Namer namer;
  ConstantEmitter constantEmitter;
  NativeEmitter get nativeEmitter => task.nativeEmitter;
  TypeTestRegistry get typeTestRegistry => task.typeTestRegistry;
  CoreClasses get coreClasses => compiler.coreClasses;

  // The full code that is written to each hunk part-file.
  Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>();

  String classesCollector;
  final Map<jsAst.Name, String> mangledFieldNames =
      new HashMap<jsAst.Name, String>();
  final Map<jsAst.Name, String> mangledGlobalFieldNames =
      new HashMap<jsAst.Name, String>();
  final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>();

  JavaScriptBackend get backend => compiler.backend;
  TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;

  String get _ => space;
  String get space => compiler.options.enableMinification ? "" : " ";
  String get n => compiler.options.enableMinification ? "" : "\n";
  String get N => compiler.options.enableMinification ? "\n" : ";\n";

  /**
   * List of expressions and statements that will be included in the
   * precompiled function.
   *
   * To save space, dart2js normally generates constructors and accessors
   * dynamically. This doesn't work in CSP mode, so dart2js emits them directly
   * when in CSP mode.
   */
  Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions =
      new Map<OutputUnit, List<jsAst.Node>>();

  Map<OutputUnit, List<jsAst.Expression>> _cspPrecompiledConstructorNames =
      new Map<OutputUnit, List<jsAst.Expression>>();

  /**
   * Accumulate properties for classes and libraries, describing their
   * static/top-level members.
   * Later, these members are emitted when the class or library is emitted.
   *
   * See [getElementDescriptor].
   */
  // TODO(ahe): Generate statics with their class, and store only libraries in
  // this map.
  final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors =
      new Map<Fragment, Map<Element, ClassBuilder>>();

  final bool generateSourceMap;

  Emitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task)
      : this.compiler = compiler,
        this.namer = namer,
        cachedEmittedConstants = compiler.cacheStrategy.newSet(),
        cachedClassBuilders = compiler.cacheStrategy.newMap(),
        cachedElements = compiler.cacheStrategy.newSet() {
    constantEmitter = new ConstantEmitter(
        compiler, namer, this.constantReference, constantListGenerator);
    containerBuilder.emitter = this;
    classEmitter.emitter = this;
    nsmEmitter.emitter = this;
    interceptorEmitter.emitter = this;
  }

  DiagnosticReporter get reporter => compiler.reporter;

  List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
    return _cspPrecompiledFunctions.putIfAbsent(
        outputUnit, () => new List<jsAst.Node>());
  }

  List<jsAst.Expression> cspPrecompiledConstructorNamesFor(
      OutputUnit outputUnit) {
    return _cspPrecompiledConstructorNames.putIfAbsent(
        outputUnit, () => new List<jsAst.Expression>());
  }

  /// Erases the precompiled information for csp mode for all output units.
  /// Used by the incremental compiler.
  void clearCspPrecompiledNodes() {
    _cspPrecompiledFunctions.clear();
    _cspPrecompiledConstructorNames.clear();
  }

  @override
  String get patchVersion => "full";

  @override
  bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
    if (constant.isFunction) return true; // Already emitted.
    if (constant.isPrimitive) return true; // Inlined.
    if (constant.isDummy) return true; // Inlined.
    // The name is null when the constant is already a JS constant.
    // TODO(floitsch): every constant should be registered, so that we can
    // share the ones that take up too much space (like some strings).
    if (namer.constantName(constant) == null) return true;
    return false;
  }

  @override
  int compareConstants(ConstantValue a, ConstantValue b) {
    // Inlined constants don't affect the order and sometimes don't even have
    // names.
    int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
    int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
    if (cmp1 + cmp2 < 2) return cmp1 - cmp2;

    // Emit constant interceptors first. Constant interceptors for primitives
    // might be used by code that builds other constants.  See Issue 18173.
    if (a.isInterceptor != b.isInterceptor) {
      return a.isInterceptor ? -1 : 1;
    }

    // Sorting by the long name clusters constants with the same constructor
    // which compresses a tiny bit better.
    int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
    if (r != 0) return r;

    // Resolve collisions in the long name by using a structural order.
    return deepCompareConstants(a, b);
  }

  @override
  jsAst.Expression constantReference(ConstantValue value) {
    if (value.isFunction) {
      FunctionConstantValue functionConstant = value;
      return isolateStaticClosureAccess(functionConstant.element);
    }

    // We are only interested in the "isInlined" part, but it does not hurt to
    // test for the other predicates.
    if (isConstantInlinedOrAlreadyEmitted(value)) {
      return constantEmitter.generate(value);
    }
    return js('#.#',
        [namer.globalObjectForConstant(value), namer.constantName(value)]);
  }

  jsAst.Expression constantInitializerExpression(ConstantValue value) {
    return constantEmitter.generate(value);
  }

  String get name => 'CodeEmitter';

  String get finishIsolateConstructorName =>
      '${namer.isolateName}.\$finishIsolateConstructor';
  String get isolatePropertiesName =>
      '${namer.isolateName}.${namer.isolatePropertiesName}';
  String get lazyInitializerProperty => r'$lazy';
  String get lazyInitializerName =>
      '${namer.isolateName}.${lazyInitializerProperty}';
  String get initName => 'init';

  jsAst.Name get makeConstListProperty =>
      namer.internalGlobal('makeConstantList');

  /// The name of the property that contains all field names.
  ///
  /// This property is added to constructors when isolate support is enabled.
  static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__";

  /// For deferred loading we communicate the initializers via this global var.
  final String deferredInitializers = r"$dart_deferred_initializers$";

  /// Contains the global state that is needed to initialize and load a
  /// deferred library.
  String get globalsHolder => r"$globals$";

  @override
  bool get supportsReflection => true;

  @override
  jsAst.Expression generateEmbeddedGlobalAccess(String global) {
    return js(generateEmbeddedGlobalAccessString(global));
  }

  String generateEmbeddedGlobalAccessString(String global) {
    // TODO(floitsch): don't use 'init' as global embedder storage.
    return '$initName.$global';
  }

  jsAst.PropertyAccess globalPropertyAccess(Element element) {
    jsAst.Name name = namer.globalPropertyName(element);
    jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
        new jsAst.VariableUse(namer.globalObjectFor(element)), name);
    return pa;
  }

  @override
  jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
    return jsAst.js('#.#',
        [namer.globalObjectFor(element), namer.lazyInitializerName(element)]);
  }

  @override
  jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
    return jsAst.js('#.#()',
        [namer.globalObjectFor(element), namer.staticClosureName(element)]);
  }

  @override
  jsAst.PropertyAccess staticFieldAccess(FieldElement element) {
    return globalPropertyAccess(element);
  }

  @override
  jsAst.PropertyAccess staticFunctionAccess(FunctionElement element) {
    return globalPropertyAccess(element);
  }

  @override
  jsAst.PropertyAccess constructorAccess(ClassElement element) {
    return globalPropertyAccess(element);
  }

  @override
  jsAst.PropertyAccess prototypeAccess(
      ClassElement element, bool hasBeenInstantiated) {
    return jsAst.js('#.prototype', constructorAccess(element));
  }

  @override
  jsAst.PropertyAccess interceptorClassAccess(ClassElement element) {
    return globalPropertyAccess(element);
  }

  @override
  jsAst.PropertyAccess typeAccess(Element element) {
    return globalPropertyAccess(element);
  }

  @override
  jsAst.Template templateForBuiltin(JsBuiltin builtin) {
    switch (builtin) {
      case JsBuiltin.dartObjectConstructor:
        return jsAst.js
            .expressionTemplateYielding(typeAccess(coreClasses.objectClass));

      case JsBuiltin.isCheckPropertyToJsConstructorName:
        int isPrefixLength = namer.operatorIsPrefix.length;
        return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)');

      case JsBuiltin.isFunctionType:
        return backend.rtiEncoder.templateForIsFunctionType;

      case JsBuiltin.rawRtiToJsConstructorName:
        return jsAst.js.expressionTemplateFor("#.$typeNameProperty");

      case JsBuiltin.rawRuntimeType:
        return jsAst.js.expressionTemplateFor("#.constructor");

      case JsBuiltin.createFunctionTypeRti:
        return backend.rtiEncoder.templateForCreateFunctionType;

      case JsBuiltin.isSubtype:
        // TODO(floitsch): move this closer to where is-check properties are
        // built.
        String isPrefix = namer.operatorIsPrefix;
        return jsAst.js
            .expressionTemplateFor("('$isPrefix' + #) in #.prototype");

      case JsBuiltin.isGivenTypeRti:
        return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #');

      case JsBuiltin.getMetadata:
        String metadataAccess =
            generateEmbeddedGlobalAccessString(embeddedNames.METADATA);
        return jsAst.js.expressionTemplateFor("$metadataAccess[#]");

      case JsBuiltin.getType:
        String typesAccess =
            generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
        return jsAst.js.expressionTemplateFor("$typesAccess[#]");

      case JsBuiltin.createDartClosureFromNameOfStaticFunction:
        // The global-functions map contains a map from name to tear-off
        // getters.
        String functionGettersMap =
            generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS);
        return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()");

      default:
        reporter.internalError(
            NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
        return null;
    }
  }

  List<jsAst.Statement> buildTrivialNsmHandlers() {
    return nsmEmitter.buildTrivialNsmHandlers();
  }

  jsAst.Statement buildNativeInfoHandler(
      jsAst.Expression infoAccess,
      jsAst.Expression constructorAccess,
      jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
      jsAst.Expression interceptorsByTagAccess,
      jsAst.Expression leafTagsAccess) {
    return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess,
        subclassReadGenerator, interceptorsByTagAccess, leafTagsAccess);
  }

  jsAst.ObjectInitializer generateInterceptedNamesSet() {
    return interceptorEmitter.generateInterceptedNamesSet();
  }

  /// In minified mode we want to keep the name for the most common core types.
  bool _isNativeTypeNeedingReflectionName(Element element) {
    if (!element.isClass) return false;
    return (element == coreClasses.intClass ||
        element == coreClasses.doubleClass ||
        element == coreClasses.numClass ||
        element == coreClasses.stringClass ||
        element == coreClasses.boolClass ||
        element == coreClasses.nullClass ||
        element == coreClasses.listClass);
  }

  /// Returns the "reflection name" of an [Element] or [Selector].
  /// The reflection name of a getter 'foo' is 'foo'.
  /// The reflection name of a setter 'foo' is 'foo='.
  /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
  /// number of required arguments, M is the number of optional arguments, and
  /// O is the named arguments.
  /// The reflection name of a constructor is similar to a regular method but
  /// starts with 'new '.
  /// The reflection name of class 'C' is 'C'.
  /// An anonymous mixin application has no reflection name.
  /// This is used by js_mirrors.dart.
  String getReflectionName(elementOrSelector, jsAst.Name mangledName) {
    String name = elementOrSelector.name;
    if (backend.shouldRetainName(name) ||
        elementOrSelector is Element &&
            // Make sure to retain names of unnamed constructors, and
            // for common native types.
            ((name == '' &&
                    backend.isAccessibleByReflection(elementOrSelector)) ||
                _isNativeTypeNeedingReflectionName(elementOrSelector))) {
      // TODO(ahe): Enable the next line when I can tell the difference between
      // an instance method and a global.  They may have the same mangled name.
      // if (recordedMangledNames.contains(mangledName)) return null;
      recordedMangledNames.add(mangledName);
      return getReflectionNameInternal(elementOrSelector, mangledName);
    }
    return null;
  }

  String getReflectionNameInternal(elementOrSelector, jsAst.Name mangledName) {
    String name = namer.privateName(elementOrSelector.memberName);
    if (elementOrSelector.isGetter) return name;
    if (elementOrSelector.isSetter) {
      if (mangledName is! SetterName) return '$name=';
      SetterName setterName = mangledName;
      jsAst.Name base = setterName.base;
      jsAst.Name getter = namer.deriveGetterName(base);
      mangledFieldNames.putIfAbsent(getter, () => name);
      assert(mangledFieldNames[getter] == name);
      recordedMangledNames.add(getter);
      // TODO(karlklose,ahe): we do not actually need to store information
      // about the name of this setter in the output, but it is needed for
      // marking the function as invokable by reflection.
      return '$name=';
    }
    if (elementOrSelector is Element && elementOrSelector.isClosure) {
      // Closures are synthesized and their name might conflict with existing
      // globals. Assign an illegal name, and make sure they don't clash
      // with each other.
      return " $name";
    }
    if (elementOrSelector is Selector ||
        elementOrSelector.isFunction ||
        elementOrSelector.isConstructor) {
      int positionalParameterCount;
      String namedArguments = '';
      bool isConstructor = false;
      if (elementOrSelector is Selector) {
        CallStructure callStructure = elementOrSelector.callStructure;
        positionalParameterCount = callStructure.positionalArgumentCount;
        namedArguments = namedParametersAsReflectionNames(callStructure);
      } else {
        FunctionElement function = elementOrSelector;
        if (function.isConstructor) {
          isConstructor = true;
          name = Elements.reconstructConstructorName(function);
        }
        FunctionSignature signature = function.functionSignature;
        positionalParameterCount = signature.requiredParameterCount;
        if (signature.optionalParametersAreNamed) {
          var names = [];
          for (Element e in signature.optionalParameters) {
            names.add(e.name);
          }
          CallStructure callStructure =
              new CallStructure(positionalParameterCount, names);
          namedArguments = namedParametersAsReflectionNames(callStructure);
        } else {
          // Named parameters are handled differently by mirrors. For unnamed
          // parameters, they are actually required if invoked
          // reflectively. Also, if you have a method c(x) and c([x]) they both
          // get the same mangled name, so they must have the same reflection
          // name.
          positionalParameterCount += signature.optionalParameterCount;
        }
      }
      String suffix = '$name:$positionalParameterCount$namedArguments';
      return (isConstructor) ? 'new $suffix' : suffix;
    }
    Element element = elementOrSelector;
    if (element.isGenerativeConstructorBody) {
      return null;
    } else if (element.isClass) {
      ClassElement cls = element;
      if (cls.isUnnamedMixinApplication) return null;
      return cls.name;
    } else if (element.isTypedef) {
      return element.name;
    }
    throw reporter.internalError(
        element, 'Do not know how to reflect on this $element.');
  }

  String namedParametersAsReflectionNames(CallStructure structure) {
    if (structure.isUnnamed) return '';
    String names = structure.getOrderedNamedArguments().join(':');
    return ':$names';
  }

  jsAst.Statement buildCspPrecompiledFunctionFor(OutputUnit outputUnit) {
    if (compiler.options.useContentSecurityPolicy) {
      // TODO(ahe): Compute a hash code.
      // TODO(sigurdm): Avoid this precompiled function. Generated
      // constructor-functions and getter/setter functions can be stored in the
      // library-description table. Setting properties on these can be moved to
      // finishClasses.
      return js.statement(
          r"""
        #precompiled = function ($collectedClasses$) {
          #norename;
          var $desc;
          #functions;
          return #result;
        };""",
          {
            'norename': new jsAst.Comment("// ::norenaming:: "),
            'precompiled':
                generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED),
            'functions': cspPrecompiledFunctionFor(outputUnit),
            'result': new jsAst.ArrayInitializer(
                cspPrecompiledConstructorNamesFor(outputUnit))
          });
    } else {
      return js.comment("Constructors are generated at runtime.");
    }
  }

  void assembleClass(
      Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
    ClassElement classElement = cls.element;
    reporter.withCurrentElement(classElement, () {
      if (compiler.options.hasIncrementalSupport) {
        ClassBuilder cachedBuilder =
            cachedClassBuilders.putIfAbsent(classElement, () {
          ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
          classEmitter.emitClass(cls, builder, fragment);
          return builder;
        });
        invariant(classElement, cachedBuilder.fields.isEmpty);
        invariant(classElement, cachedBuilder.superName == null);
        invariant(classElement, cachedBuilder.functionType == null);
        invariant(classElement, cachedBuilder.fieldMetadata == null);
        enclosingBuilder.properties.addAll(cachedBuilder.properties);
      } else {
        classEmitter.emitClass(cls, enclosingBuilder, fragment);
      }
    });
  }

  void assembleStaticFunctions(
      Iterable<Method> staticFunctions, Fragment fragment) {
    if (staticFunctions == null) return;

    for (Method method in staticFunctions) {
      Element element = method.element;
      // We need to filter out null-elements for the interceptors.
      // TODO(floitsch): use the precomputed interceptors here.
      if (element == null) continue;
      ClassBuilder builder = new ClassBuilder.forStatics(element, namer);
      containerBuilder.addMemberMethod(method, builder);
      getElementDescriptor(element, fragment)
          .properties
          .addAll(builder.properties);
    }
  }

  jsAst.Statement buildStaticNonFinalFieldInitializations(
      OutputUnit outputUnit) {
    jsAst.Statement buildInitialization(
        Element element, jsAst.Expression initialValue) {
      return js.statement('${namer.staticStateHolder}.# = #',
          [namer.globalPropertyName(element), initialValue]);
    }

    bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit);
    JavaScriptConstantCompiler handler = backend.constants;
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit];
    // If the outputUnit does not contain any static non-final fields, then
    // [fields] is `null`.
    if (fields != null) {
      for (FieldElement element in fields) {
        reporter.withCurrentElement(element, () {
          ConstantValue constant = handler.getConstantValue(element.constant);
          parts.add(buildInitialization(element, constantReference(constant)));
        });
      }
    }

    if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) {
      // In the main output-unit we output a stub initializer for deferred
      // variables, so that `isolateProperties` stays a fast object.
      outputStaticNonFinalFieldLists.forEach(
          (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) {
        if (fieldsOutputUnit == outputUnit) return; // Skip the main unit.
        for (Element element in fields) {
          reporter.withCurrentElement(element, () {
            parts.add(buildInitialization(element, jsAst.number(0)));
          });
        }
      });
    }

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildLazilyInitializedStaticFields(
      Iterable<StaticField> lazyFields,
      {bool isMainFragment: true}) {
    if (lazyFields.isNotEmpty) {
      needsLazyInitializer = true;
      List<jsAst.Expression> laziesInfo =
          buildLaziesInfo(lazyFields, isMainFragment);
      return js.statement(
          '''
      (function(lazies) {
        for (var i = 0; i < lazies.length; ) {
          var fieldName = lazies[i++];
          var getterName = lazies[i++];
          var lazyValue = lazies[i++];
          if (#notMinified) {
            var staticName = lazies[i++];
          }
          if (#isDeferredFragment) {
            var fieldHolder = lazies[i++];
          }
          // We build the lazy-check here:
          //   lazyInitializer(fieldName, getterName, lazyValue, staticName);
          // 'staticName' is used for error reporting in non-minified mode.
          // 'lazyValue' must be a closure that constructs the initial value.
          if (#isMainFragment) {
            if (#notMinified) {
              #lazy(fieldName, getterName, lazyValue, staticName);
            } else {
              #lazy(fieldName, getterName, lazyValue);
            }
          } else {
            if (#notMinified) {
              #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder);
            } else {
              #lazy(fieldName, getterName, lazyValue, null, fieldHolder);
            }
          }
        }
      })(#laziesInfo)
      ''',
          {
            'notMinified': !compiler.options.enableMinification,
            'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
            'lazy': js(lazyInitializerName),
            'isMainFragment': isMainFragment,
            'isDeferredFragment': !isMainFragment
          });
    } else {
      return js.comment("No lazy statics.");
    }
  }

  List<jsAst.Expression> buildLaziesInfo(
      Iterable<StaticField> lazies, bool isMainFragment) {
    List<jsAst.Expression> laziesInfo = <jsAst.Expression>[];
    for (StaticField field in lazies) {
      laziesInfo.add(js.quoteName(field.name));
      laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name)));
      laziesInfo.add(field.code);
      if (!compiler.options.enableMinification) {
        laziesInfo.add(js.quoteName(field.name));
      }
      if (!isMainFragment) {
        laziesInfo.add(js('#', field.holder.name));
      }
    }
    return laziesInfo;
  }

  // TODO(sra): Remove this unused function.
  jsAst.Expression buildLazilyInitializedStaticField(VariableElement element,
      {String isolateProperties}) {
    jsAst.Expression code = backend.generatedCode[element];
    // The code is null if we ended up not needing the lazily
    // initialized field after all because of constant folding
    // before code generation.
    if (code == null) return null;
    // The code only computes the initial value. We build the lazy-check
    // here:
    //   lazyInitializer(fieldName, getterName, initial, name, prototype);
    // The name is used for error reporting. The 'initial' must be a
    // closure that constructs the initial value.
    if (isolateProperties != null) {
      // This is currently only used in incremental compilation to patch
      // in new lazy values.
      return js('#(#,#,#,#,#)', [
        js(lazyInitializerName),
        js.quoteName(namer.globalPropertyName(element)),
        js.quoteName(namer.lazyInitializerName(element)),
        code,
        js.string(element.name),
        isolateProperties
      ]);
    }

    if (compiler.options.enableMinification) {
      return js('#(#,#,#)', [
        js(lazyInitializerName),
        js.quoteName(namer.globalPropertyName(element)),
        js.quoteName(namer.lazyInitializerName(element)),
        code
      ]);
    } else {
      return js('#(#,#,#,#)', [
        js(lazyInitializerName),
        js.quoteName(namer.globalPropertyName(element)),
        js.quoteName(namer.lazyInitializerName(element)),
        code,
        js.string(element.name)
      ]);
    }
  }

  jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit);

    if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) {
      jsAst.Expression metadataAccess =
          generateEmbeddedGlobalAccess(embeddedNames.METADATA);
      jsAst.Expression typesAccess =
          generateEmbeddedGlobalAccess(embeddedNames.TYPES);

      parts
        ..add(js.statement('# = #;', [metadataAccess, program.metadata]))
        ..add(js.statement('# = #;', [typesAccess, types]));
    } else if (types != null) {
      parts.add(js.statement('var ${namer.deferredTypesName} = #;', types));
    }
    return new jsAst.Block(parts);
  }

  jsAst.Statement buildCompileTimeConstants(List<Constant> constants,
      {bool isMainFragment}) {
    assert(isMainFragment != null);

    if (constants.isEmpty) return js.comment("No constants in program.");
    List<jsAst.Statement> parts = <jsAst.Statement>[];
    if (compiler.options.hasIncrementalSupport && isMainFragment) {
      parts = cachedEmittedConstantsAst;
    }
    for (Constant constant in constants) {
      ConstantValue constantValue = constant.value;
      if (compiler.options.hasIncrementalSupport && isMainFragment) {
        if (cachedEmittedConstants.contains(constantValue)) continue;
        cachedEmittedConstants.add(constantValue);
      }
      parts.add(buildConstantInitializer(constantValue));
    }

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildConstantInitializer(ConstantValue constant) {
    jsAst.Name name = namer.constantName(constant);
    jsAst.Statement initializer = js.statement('#.# = #', [
      namer.globalObjectForConstant(constant),
      name,
      constantInitializerExpression(constant)
    ]);
    compiler.dumpInfoTask.registerConstantAst(constant, initializer);
    return initializer;
  }

  jsAst.Expression constantListGenerator(jsAst.Expression array) {
    // TODO(floitsch): there is no harm in caching the template.
    return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
  }

  jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) {
    if (outputContainsConstantList) {
      return js.statement(
          r'''
          // Functions are stored in the hidden class and not as properties in
          // the object. We never actually look at the value, but only want
          // to know if the property exists.
          #.# = function (list) {
            list.immutable$list = Array;
            list.fixed$length = Array;
            return list;
          }''',
          [namer.isolateName, makeConstListProperty]);
    } else {
      return js.comment("Output contains no constant list.");
    }
  }

  jsAst.Statement buildFunctionThatReturnsNull() {
    return js.statement('#.# = function() {}',
        [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
  }

  jsAst.Expression generateFunctionThatReturnsNull() {
    return js("#.#",
        [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
  }

  buildMain(jsAst.Statement invokeMain) {
    if (compiler.isMockCompilation) return js.comment("Mock compilation");

    List<jsAst.Statement> parts = <jsAst.Statement>[];

    if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
      parts.add(NativeGenerator.generateIsolateAffinityTagInitialization(
          backend,
          generateEmbeddedGlobalAccess,
          js(
              """
        // On V8, the 'intern' function converts a string to a symbol, which
        // makes property access much faster.
        function (s) {
          var o = {};
          o[s] = 1;
          return Object.keys(convertToFastObject(o))[0];
        }""",
              [])));
    }

    parts
      ..add(js.comment('BEGIN invoke [main].'))
      ..add(invokeMain)
      ..add(js.comment('END invoke [main].'));

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildInitFunction(bool outputContainsConstantList) {
    jsAst.Expression allClassesAccess =
        generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
    jsAst.Expression getTypeFromNameAccess =
        generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME);
    jsAst.Expression interceptorsByTagAccess =
        generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
    jsAst.Expression leafTagsAccess =
        generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
    jsAst.Expression finishedClassesAccess =
        generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
    jsAst.Expression cyclicThrow =
        staticFunctionAccess(backend.helpers.cyclicThrowHelper);
    jsAst.Expression laziesAccess =
        generateEmbeddedGlobalAccess(embeddedNames.LAZIES);

    return js.statement(
        '''
      function init() {
        $isolatePropertiesName = Object.create(null);
        #allClasses = map();
        #getTypeFromName = function(name) {return #allClasses[name];};
        #interceptorsByTag = map();
        #leafTags = map();
        #finishedClasses = map();

        if (#needsLazyInitializer) {
          // [staticName] is only provided in non-minified mode. If missing, we
          // fall back to [fieldName]. Likewise, [prototype] is optional and
          // defaults to the isolateProperties object.
          $lazyInitializerName = function (fieldName, getterName, lazyValue,
                                           staticName, prototype) {
            if (!#lazies) #lazies = Object.create(null);
            #lazies[fieldName] = getterName;

            // 'prototype' will be undefined except if we are doing an update
            // during incremental compilation. In this case we put the lazy
            // field directly on the isolate instead of the isolateProperties.
            prototype = prototype || $isolatePropertiesName;
            var sentinelUndefined = {};
            var sentinelInProgress = {};
            prototype[fieldName] = sentinelUndefined;

            prototype[getterName] = function () {
              var result = this[fieldName];
              try {
                if (result === sentinelUndefined) {
                  this[fieldName] = sentinelInProgress;

                  try {
                    result = this[fieldName] = lazyValue();
                  } finally {
                    // Use try-finally, not try-catch/throw as it destroys the
                    // stack trace.
                    if (result === sentinelUndefined)
                      this[fieldName] = null;
                  }
                } else {
                  if (result === sentinelInProgress)
                    // In minified mode, static name is not provided, so fall
                    // back to the minified fieldName.
                    #cyclicThrow(staticName || fieldName);
                }

                return result;
              } finally {
                this[getterName] = function() { return this[fieldName]; };
              }
            }
          }
        }

        // We replace the old Isolate function with a new one that initializes
        // all its fields with the initial (and often final) value of all
        // globals.
        //
        // We also copy over old values like the prototype, and the
        // isolateProperties themselves.
        $finishIsolateConstructorName = function (oldIsolate) {
          var isolateProperties = oldIsolate.#isolatePropertiesName;
          function Isolate() {

            var staticNames = Object.keys(isolateProperties);
            for (var i = 0; i < staticNames.length; i++) {
              var staticName = staticNames[i];
              this[staticName] = isolateProperties[staticName];
            }

            // Reset lazy initializers to null.
            // When forcing the object to fast mode (below) v8 will consider
            // functions as part the object's map. Since we will change them
            // (after the first call to the getter), we would have a map
            // transition.
            var lazies = init.lazies;
            var lazyInitializers = lazies ? Object.keys(lazies) : [];
            for (var i = 0; i < lazyInitializers.length; i++) {
               this[lazies[lazyInitializers[i]]] = null;
            }

            // Use the newly created object as prototype. In Chrome,
            // this creates a hidden class for the object and makes
            // sure it is fast to access.
            function ForceEfficientMap() {}
            ForceEfficientMap.prototype = this;
            new ForceEfficientMap();

            // Now, after being a fast map we can set the lazies again.
            for (var i = 0; i < lazyInitializers.length; i++) {
              var lazyInitName = lazies[lazyInitializers[i]];
              this[lazyInitName] = isolateProperties[lazyInitName];
            }
          }
          Isolate.prototype = oldIsolate.prototype;
          Isolate.prototype.constructor = Isolate;
          Isolate.#isolatePropertiesName = isolateProperties;
          if (#outputContainsConstantList) {
            Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty;
          }
          Isolate.#functionThatReturnsNullProperty =
              oldIsolate.#functionThatReturnsNullProperty;
          if (#hasIncrementalSupport) {
            Isolate.#lazyInitializerProperty =
                oldIsolate.#lazyInitializerProperty;
          }
          return Isolate;
      }

      }''',
        {
          'allClasses': allClassesAccess,
          'getTypeFromName': getTypeFromNameAccess,
          'interceptorsByTag': interceptorsByTagAccess,
          'leafTags': leafTagsAccess,
          'finishedClasses': finishedClassesAccess,
          'needsLazyInitializer': needsLazyInitializer,
          'lazies': laziesAccess,
          'cyclicThrow': cyclicThrow,
          'isolatePropertiesName': namer.isolatePropertiesName,
          'outputContainsConstantList': outputContainsConstantList,
          'makeConstListProperty': makeConstListProperty,
          'functionThatReturnsNullProperty':
              backend.rtiEncoder.getFunctionThatReturnsNullName,
          'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
          'lazyInitializerProperty': lazyInitializerProperty,
        });
  }

  jsAst.Statement buildConvertToFastObjectFunction() {
    List<jsAst.Statement> debugCode = <jsAst.Statement>[];
    if (DEBUG_FAST_OBJECTS) {
      debugCode.add(js.statement(r'''
        // The following only works on V8 when run with option
        // "--allow-natives-syntax".  We use'new Function' because the
         // miniparser does not understand V8 native syntax.
        if (typeof print === "function") {
          var HasFastProperties =
            new Function("a", "return %HasFastProperties(a)");
          print("Size of global object: "
                   + String(Object.getOwnPropertyNames(properties).length)
                   + ", fast properties " + HasFastProperties(properties));
        }'''));
    }

    return js.statement(
        r'''
      function convertToFastObject(properties) {
        // Create an instance that uses 'properties' as prototype. This should
        // make 'properties' a fast object.
        function MyClass() {};
        MyClass.prototype = properties;
        new MyClass();
        #;
        return properties;
      }''',
        [debugCode]);
  }

  jsAst.Statement buildConvertToSlowObjectFunction() {
    return js.statement(r'''
    function convertToSlowObject(properties) {
      // Add and remove a property to make the object transition into hashmap
      // mode.
      properties.__MAGIC_SLOW_PROPERTY = 1;
      delete properties.__MAGIC_SLOW_PROPERTY;
      return properties;
    }''');
  }

  jsAst.Statement buildSupportsDirectProtoAccess() {
    jsAst.Statement supportsDirectProtoAccess;

    if (compiler.options.hasIncrementalSupport) {
      supportsDirectProtoAccess = js.statement(r'''
        var supportsDirectProtoAccess = false;
      ''');
    } else {
      supportsDirectProtoAccess = js.statement(r'''
        var supportsDirectProtoAccess = (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;
        })();
      ''');
    }

    return supportsDirectProtoAccess;
  }

  jsAst.Expression generateLibraryDescriptor(
      LibraryElement library, Fragment fragment) {
    var uri = "";
    if (!compiler.options.enableMinification || backend.mustPreserveUris) {
      uri = library.canonicalUri;
      if (uri.scheme == 'file' && compiler.options.outputUri != null) {
        uri =
            relativize(compiler.options.outputUri, library.canonicalUri, false);
      }
    }

    String libraryName =
        (!compiler.options.enableMinification || backend.mustRetainLibraryNames)
            ? library.libraryName
            : "";

    jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);

    ClassBuilder descriptor = elementDescriptors[fragment][library];

    jsAst.ObjectInitializer initializer;
    if (descriptor == null) {
      // Nothing of the library was emitted.
      // TODO(floitsch): this should not happen. We currently have an example
      // with language/prefix6_negative_test.dart where we have an instance
      // method without its corresponding class.
      initializer = new jsAst.ObjectInitializer([]);
    } else {
      initializer = descriptor.toObjectInitializer();
    }

    compiler.dumpInfoTask.registerElementAst(library, metadata);
    compiler.dumpInfoTask.registerElementAst(library, initializer);

    List<jsAst.Expression> parts = <jsAst.Expression>[];
    parts
      ..add(js.string(libraryName))
      ..add(js.string(uri.toString()))
      ..add(metadata == null ? new jsAst.ArrayHole() : metadata)
      ..add(js('#', namer.globalObjectFor(library)))
      ..add(initializer);
    if (library == compiler.mainApp) {
      parts.add(js.number(1));
    }

    return new jsAst.ArrayInitializer(parts);
  }

  void assemblePrecompiledConstructor(
      OutputUnit outputUnit,
      jsAst.Name constructorName,
      jsAst.Expression constructorAst,
      List<jsAst.Name> fields) {
    cspPrecompiledFunctionFor(outputUnit)
        .add(new jsAst.FunctionDeclaration(constructorName, constructorAst));

    String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
    bool hasIsolateSupport = compiler.resolverWorld.hasIsolateSupport;
    jsAst.Node fieldNamesArray;
    if (hasIsolateSupport) {
      fieldNamesArray =
          new jsAst.ArrayInitializer(fields.map(js.quoteName).toList());
    } else {
      fieldNamesArray = new jsAst.LiteralNull();
    }

    cspPrecompiledFunctionFor(outputUnit).add(js.statement(
        r'''
        {
          #constructorName.#typeNameProperty = #constructorNameString;
          // IE does not have a name property.
          if (!("name" in #constructorName))
              #constructorName.name = #constructorNameString;
          $desc = $collectedClasses$.#constructorName[1];
          #constructorName.prototype = $desc;
          ''' /* next string is not a raw string */ '''
          if (#hasIsolateSupport) {
            #constructorName.$fieldNamesProperty = #fieldNamesArray;
          }
        }''',
        {
          "constructorName": constructorName,
          "typeNameProperty": typeNameProperty,
          "constructorNameString": js.quoteName(constructorName),
          "hasIsolateSupport": hasIsolateSupport,
          "fieldNamesArray": fieldNamesArray
        }));

    cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName));
  }

  void assembleTypedefs(Program program) {
    Fragment mainFragment = program.mainFragment;
    OutputUnit mainOutputUnit = mainFragment.outputUnit;

    // Emit all required typedef declarations into the main output unit.
    // TODO(karlklose): unify required classes and typedefs to declarations
    // and have builders for each kind.
    for (TypedefElement typedef in typedefsNeededForReflection) {
      LibraryElement library = typedef.library;
      // TODO(karlklose): add a TypedefBuilder and move this code there.
      DartType type = typedef.alias;
      // TODO(zarah): reify type variables once reflection on type arguments of
      // typedefs is supported.
      jsAst.Expression typeIndex =
          task.metadataCollector.reifyType(type, ignoreTypeVariables: true);
      ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer);
      builder.addPropertyByName(
          embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex);
      builder.addPropertyByName(
          embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, js.boolean(true));

      // We can be pretty sure that the objectClass is initialized, since
      // typedefs are only emitted with reflection, which requires lots of
      // classes.
      assert(coreClasses.objectClass != null);
      builder.superName = namer.className(coreClasses.objectClass);
      jsAst.Node declaration = builder.toObjectInitializer();
      jsAst.Name mangledName = namer.globalPropertyName(typedef);
      String reflectionName = getReflectionName(typedef, mangledName);
      getElementDescriptor(library, mainFragment)
        ..addProperty(mangledName, declaration)
        ..addPropertyByName("+$reflectionName", js.string(''));
      // Also emit a trivial constructor for CSP mode.
      jsAst.Name constructorName = mangledName;
      jsAst.Expression constructorAst = js('function() {}');
      List<jsAst.Name> fieldNames = [];
      assemblePrecompiledConstructor(
          mainOutputUnit, constructorName, constructorAst, fieldNames);
    }
  }

  jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    parts.add(js.comment("""
      // The global objects start as so-called "slow objects". For V8, this
      // means that it won't try to make map transitions as we add properties
      // to these objects. Later on, we attempt to turn these objects into
      // fast objects by calling "convertToFastObject" (see
      // [emitConvertToFastObjectFunction]).
      """));

    for (String globalObject in Namer.reservedGlobalObjectNames) {
      if (isProgramSplit) {
        String template =
            "var #globalObject = #globalsHolder.#globalObject = map();";
        parts.add(js.statement(template,
            {"globalObject": globalObject, "globalsHolder": globalsHolder}));
      } else {
        parts.add(js.statement(
            "var #globalObject = map();", {"globalObject": globalObject}));
      }
    }

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildConvertGlobalObjectToFastObjects() {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    for (String globalObject in Namer.reservedGlobalObjectNames) {
      parts.add(js.statement(
          '#globalObject = convertToFastObject(#globalObject);',
          {"globalObject": globalObject}));
    }

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildDebugFastObjectCode() {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    if (DEBUG_FAST_OBJECTS) {
      parts.add(js.statement(r'''
          // The following only works on V8 when run with option
          // "--allow-natives-syntax".  We use'new Function' because the
          // miniparser does not understand V8 native syntax.
          if (typeof print === "function") {
            var HasFastProperties =
              new Function("a", "return %HasFastProperties(a)");
            print("Size of global helper object: "
                   + String(Object.getOwnPropertyNames(H).length)
                   + ", fast properties " + HasFastProperties(H));
            print("Size of global platform object: "
                   + String(Object.getOwnPropertyNames(P).length)
                   + ", fast properties " + HasFastProperties(P));
            print("Size of global dart:html object: "
                   + String(Object.getOwnPropertyNames(W).length)
                   + ", fast properties " + HasFastProperties(W));
            print("Size of isolate properties object: "
                   + String(Object.getOwnPropertyNames($).length)
                   + ", fast properties " + HasFastProperties($));
            print("Size of constant object: "
                   + String(Object.getOwnPropertyNames(C).length)
                   + ", fast properties " + HasFastProperties(C));
            var names = Object.getOwnPropertyNames($);
            for (var i = 0; i < names.length; i++) {
              print("$." + names[i]);
            }
          }
       '''));

      for (String object in Namer.userGlobalObjects) {
        parts.add(js.statement(
            '''
          if (typeof print === "function") {
            print("Size of " + #objectString + ": "
                  + String(Object.getOwnPropertyNames(#object).length)
                  + ", fast properties " + HasFastProperties(#object));
          }
        ''',
            {"object": object, "objectString": js.string(object)}));
      }
    }

    return new jsAst.Block(parts);
  }

  jsAst.Statement buildMangledNames() {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    if (!mangledFieldNames.isEmpty) {
      List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort();
      var properties = [];
      for (jsAst.Name key in keys) {
        var value = js.string(mangledFieldNames[key]);
        properties.add(new jsAst.Property(key, value));
      }

      jsAst.Expression mangledNamesAccess =
          generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
      var map = new jsAst.ObjectInitializer(properties);
      parts.add(js.statement('# = #', [mangledNamesAccess, map]));
    }

    if (!mangledGlobalFieldNames.isEmpty) {
      List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()..sort();
      List<jsAst.Property> properties = <jsAst.Property>[];
      for (jsAst.Name key in keys) {
        jsAst.Literal value = js.string(mangledGlobalFieldNames[key]);
        properties.add(new jsAst.Property(js.quoteName(key), value));
      }
      jsAst.Expression mangledGlobalNamesAccess =
          generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
      jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
      parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
    }

    return new jsAst.Block(parts);
  }

  void checkEverythingEmitted(Iterable<Element> elements) {
    List<Element> pendingStatics;
    if (!compiler.options.hasIncrementalSupport) {
      pendingStatics =
          Elements.sortedByPosition(elements.where((e) => !e.isLibrary));

      pendingStatics.forEach((element) => reporter.reportInfo(
          element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
    }

    if (pendingStatics != null && !pendingStatics.isEmpty) {
      reporter.internalError(
          pendingStatics.first, 'Pending statics (see above).');
    }
  }

  void assembleLibrary(Library library, Fragment fragment) {
    LibraryElement libraryElement = library.element;

    assembleStaticFunctions(library.statics, fragment);

    ClassBuilder libraryBuilder =
        getElementDescriptor(libraryElement, fragment);
    for (Class cls in library.classes) {
      assembleClass(cls, libraryBuilder, fragment);
    }

    classEmitter.emitFields(library, libraryBuilder, emitStatics: true);
  }

  void assembleProgram(Program program) {
    for (Fragment fragment in program.fragments) {
      for (Library library in fragment.libraries) {
        assembleLibrary(library, fragment);
      }
    }
    assembleTypedefs(program);
  }

  jsAst.Statement buildDeferredHeader() {
    /// For deferred loading we communicate the initializers via this global
    /// variable. The deferred hunks will add their initialization to this.
    /// The semicolon is important in minified mode, without it the
    /// following parenthesis looks like a call to the object literal.
    return js.statement(
        'self.#deferredInitializers = '
        'self.#deferredInitializers || Object.create(null);',
        {'deferredInitializers': deferredInitializers});
  }

  jsAst.Program buildOutputAstForMain(Program program,
      Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
    MainFragment mainFragment = program.mainFragment;
    OutputUnit mainOutputUnit = mainFragment.outputUnit;
    bool isProgramSplit = program.isSplit;

    List<jsAst.Statement> statements = <jsAst.Statement>[];

    statements..add(buildGeneratedBy())..add(js.comment(HOOKS_API_USAGE));

    if (isProgramSplit) {
      statements.add(buildDeferredHeader());
    }

    // Collect the AST for the decriptors
    Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment];
    if (descriptors == null) descriptors = const {};

    checkEverythingEmitted(descriptors.keys);

    Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit];
    if (libraries == null) libraries = <LibraryElement>[];

    List<jsAst.Expression> parts = <jsAst.Expression>[];
    for (LibraryElement library in Elements.sortedByPosition(libraries)) {
      parts.add(generateLibraryDescriptor(library, mainFragment));
      descriptors.remove(library);
    }

    if (descriptors.isNotEmpty) {
      List<Element> remainingLibraries =
          descriptors.keys.where((Element e) => e is LibraryElement).toList();

      // The remaining descriptors are only accessible through reflection.
      // The program builder does not collect libraries that only
      // contain typedefs that are used for reflection.
      for (LibraryElement element in remainingLibraries) {
        assert(element is LibraryElement ||
            compiler.options.hasIncrementalSupport);
        if (element is LibraryElement) {
          parts.add(generateLibraryDescriptor(element, mainFragment));
          descriptors.remove(element);
        }
      }
    }
    jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts);

    // Using a named function here produces easier to read stack traces in
    // Chrome/V8.
    statements.add(js.statement(
        """
    (function() {
       // No renaming in the top-level function to save the locals for the
       // nested context where they will be used more. We have to put the
       // comment into a hole as the parser strips out comments right away.
       #disableVariableRenaming;
       #supportsDirectProtoAccess;

       if (#hasIncrementalSupport) {
         #helper = #helper || Object.create(null);
         #helper.patch = function(a) { eval(a)};
         #helper.schemaChange = #schemaChange;
         #helper.addMethod = #addMethod;
         #helper.extractStubs =
           function(array, name, isStatic, originalDescriptor) {
             var descriptor = Object.create(null);
             this.addStubs(descriptor, array, name, isStatic, []);
             return descriptor;
            };
       }

       if (#isProgramSplit) {
         /// We collect all the global state, so it can be passed to the
         /// initializer of deferred files.
         var #globalsHolder = Object.create(null)
       }

       // [map] returns an object that V8 shouldn't try to optimize with a
       // hidden class. This prevents a potential performance problem where V8
       // tries to build a hidden class for an object used as a hashMap.
       // It requires fewer characters to declare a variable as a parameter than
       // with `var`.
       function map(x) {
         x = Object.create(null);
         x.x = 0;
         delete x.x;
         return x;
       }

       #globalObjectSetup;

       function #isolateName() {}

       if (#isProgramSplit) {
         #globalsHolder.#isolateName = #isolateName;
         #globalsHolder.#initName = #initName;
         #globalsHolder.#setupProgramName = #setupProgramName;
       }

       init();

       #mangledNames;

       #cspPrecompiledFunctions;

       #setupProgram;

       #functionThatReturnsNull;

       // The argument to reflectionDataParser is assigned to a temporary 'dart'
       // so that 'dart.' will appear as the prefix to dart methods in stack
       // traces and profile entries.
       var dart = #descriptors;

       #setupProgramName(dart, 0);

       #getInterceptorMethods;
       #oneShotInterceptors;

       #makeConstantList;

       // We abuse the short name used for the isolate here to store
       // the isolate properties. This is safe as long as the real isolate
       // object does not exist yet.
       var ${namer.staticStateHolder} = #isolatePropertiesName;

       // Constants in checked mode call into RTI code to set type information
       // which may need getInterceptor (and one-shot interceptor) methods, so
       // we have to make sure that [emitGetInterceptorMethods] and
       // [emitOneShotInterceptors] have been called.
       #compileTimeConstants;

       // Static field initializations require the classes and compile-time
       // constants to be set up.
       #staticNonFinalInitializers;

       ${namer.staticStateHolder} = null;

       #deferredBoilerPlate;

       #typeToInterceptorMap;

       #lazyStaticFields;

       #isolateName = $finishIsolateConstructorName(#isolateName);

       ${namer.staticStateHolder} = new #isolateName();

       #metadata;

       #convertToFastObject;
       #convertToSlowObject;

       #convertGlobalObjectsToFastObjects;
       #debugFastObjects;

       #init;

       #main;
    })();
    """,
        {
          "disableVariableRenaming": js.comment("/* ::norenaming:: */"),
          "hasIncrementalSupport": compiler.options.hasIncrementalSupport,
          "helper": js('this.#', [namer.incrementalHelperName]),
          "schemaChange": buildSchemaChangeFunction(),
          "addMethod": buildIncrementalAddMethod(),
          "isProgramSplit": isProgramSplit,
          "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(),
          "globalsHolder": globalsHolder,
          "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit),
          "isolateName": namer.isolateName,
          "isolatePropertiesName": js(isolatePropertiesName),
          "initName": initName,
          "functionThatReturnsNull": buildFunctionThatReturnsNull(),
          "mangledNames": buildMangledNames(),
          "setupProgram":
              buildSetupProgram(program, compiler, backend, namer, this),
          "setupProgramName": setupProgramName,
          "descriptors": descriptorsAst,
          "cspPrecompiledFunctions":
              buildCspPrecompiledFunctionFor(mainOutputUnit),
          "getInterceptorMethods":
              interceptorEmitter.buildGetInterceptorMethods(),
          "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(),
          "makeConstantList":
              buildMakeConstantList(program.outputContainsConstantList),
          "compileTimeConstants": buildCompileTimeConstants(
              mainFragment.constants,
              isMainFragment: true),
          "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes),
          "staticNonFinalInitializers":
              buildStaticNonFinalFieldInitializations(mainOutputUnit),
          "typeToInterceptorMap":
              interceptorEmitter.buildTypeToInterceptorMap(program),
          "lazyStaticFields": buildLazilyInitializedStaticFields(
              mainFragment.staticLazilyInitializedFields),
          "metadata": buildMetadata(program, mainOutputUnit),
          "convertToFastObject": buildConvertToFastObjectFunction(),
          "convertToSlowObject": buildConvertToSlowObjectFunction(),
          "convertGlobalObjectsToFastObjects":
              buildConvertGlobalObjectToFastObjects(),
          "debugFastObjects": buildDebugFastObjectCode(),
          "init": buildInitFunction(program.outputContainsConstantList),
          "main": buildMain(mainFragment.invokeMain)
        }));

    return new jsAst.Program(statements);
  }

  void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) {
    LineColumnCollector lineColumnCollector;
    List<CodeOutputListener> codeOutputListeners;
    if (generateSourceMap) {
      lineColumnCollector = new LineColumnCollector();
      codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
    }

    CodeOutput mainOutput = new StreamCodeOutput(
        compiler.outputProvider('', 'js'), codeOutputListeners);
    outputBuffers[mainOutputUnit] = mainOutput;

    mainOutput.addBuffer(jsAst.createCodeBuffer(program, compiler,
        monitor: compiler.dumpInfoTask));

    if (compiler.options.deferredMapUri != null) {
      outputDeferredMap();
    }

    if (generateSourceMap) {
      mainOutput.add(generateSourceMapTag(
          compiler.options.sourceMapUri, compiler.options.outputUri));
    }

    mainOutput.close();

    if (generateSourceMap) {
      outputSourceMap(mainOutput, lineColumnCollector, '',
          compiler.options.sourceMapUri, compiler.options.outputUri);
    }
  }

  /// Used by incremental compilation to patch up the prototype of
  /// [oldConstructor] for use as prototype of [newConstructor].
  jsAst.Fun buildSchemaChangeFunction() {
    if (!compiler.options.hasIncrementalSupport) return null;
    return js('''
function(newConstructor, oldConstructor, superclass) {
  // Invariant: newConstructor.prototype has no interesting properties besides
  // generated accessors. These are copied to oldPrototype which will be
  // updated by other incremental changes.
  if (superclass != null) {
    this.inheritFrom(newConstructor, superclass);
  }
  var oldPrototype = oldConstructor.prototype;
  var newPrototype = newConstructor.prototype;
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  for (var property in newPrototype) {
    if (hasOwnProperty.call(newPrototype, property)) {
      // Copy generated accessors.
      oldPrototype[property] = newPrototype[property];
    }
  }
  oldPrototype.__proto__ = newConstructor.prototype.__proto__;
  oldPrototype.constructor = newConstructor;
  newConstructor.prototype = oldPrototype;
  return newConstructor;
}''');
  }

  /// Used by incremental compilation to patch up an object ([holder]) with a
  /// new (or updated) method.  [arrayOrFunction] is either the new method, or
  /// an array containing the method (see
  /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the
  /// new method. [isStatic] tells if method is static (or
  /// top-level). [globalFunctionsAccess] is a reference to
  /// [embeddedNames.GLOBAL_FUNCTIONS].
  jsAst.Fun buildIncrementalAddMethod() {
    if (!compiler.options.hasIncrementalSupport) return null;
    return js(r"""
function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
  var arrayOrFunction = originalDescriptor[name];
  var method;
  if (arrayOrFunction.constructor === Array) {
    var existing = holder[name];
    var array = arrayOrFunction;

    // Each method may have a number of stubs associated. For example, if an
    // instance method supports multiple arguments, a stub for each matching
    // selector. There is also a getter stub for tear-off getters. For example,
    // an instance method foo([a]) may have the following stubs: foo$0, foo$1,
    // and get$foo (here exemplified using unminified names).
    // [extractStubs] returns a JavaScript object whose own properties
    // corresponds to the stubs.
    var descriptor =
        this.extractStubs(array, name, isStatic, originalDescriptor);
    method = descriptor[name];

    // Iterate through the properties of descriptor and copy the stubs to the
    // existing holder (for instance methods, a prototype).
    for (var property in descriptor) {
      if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue;
      var stub = descriptor[property];
      var existingStub = holder[property];
      if (stub === method || !existingStub || !stub.$getterStub) {
        // Not replacing an existing getter stub.
        holder[property] = stub;
        continue;
      }
      if (!stub.$getterStub) {
        var error = new Error('Unexpected stub.');
        error.stub = stub;
        throw error;
      }

      // Existing getter stubs need special treatment as they may already have
      // been called and produced a closure.
      this.pendingStubs = this.pendingStubs || [];
      // It isn't safe to invoke the stub yet.
      this.pendingStubs.push((function(holder, stub, existingStub, existing,
                                       method) {
        return function() {
          var receiver = isStatic ? holder : new holder.constructor();
          // Invoke the existing stub to obtain the tear-off closure.
          existingStub = existingStub.call(receiver);
          // Invoke the new stub to create a tear-off closure we can use as a
          // prototype.
          stub = stub.call(receiver);

          // Copy the properties from the new tear-off's prototype to the
          // prototype of the existing tear-off.
          var newProto = stub.constructor.prototype;
          var existingProto = existingStub.constructor.prototype;
          for (var stubProperty in newProto) {
            if (!Object.prototype.hasOwnProperty.call(newProto, stubProperty))
              continue;
            existingProto[stubProperty] = newProto[stubProperty];
          }

          // Update all the existing stub's references to [existing] to
          // [method]. Instance tear-offs are call-by-name, so this isn't
          // necessary for those.
          if (!isStatic) return;
          for (var reference in existingStub) {
            if (existingStub[reference] === existing) {
              existingStub[reference] = method;
            }
          }
        }
      })(holder, stub, existingStub, existing, method));
    }
  } else {
    method = arrayOrFunction;
    holder[name] = method;
  }
  if (isStatic) globalFunctionsAccess[name] = method;
}""");
  }

  Map<OutputUnit, jsAst.Expression> buildDescriptorsForOutputUnits(
      Program program) {
    Map<OutputUnit, jsAst.Expression> outputs =
        new Map<OutputUnit, jsAst.Expression>();

    for (Fragment fragment in program.deferredFragments) {
      OutputUnit outputUnit = fragment.outputUnit;

      Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment];

      if (descriptors != null && descriptors.isNotEmpty) {
        Iterable<LibraryElement> libraries = outputLibraryLists[outputUnit];
        if (libraries == null) libraries = [];

        // TODO(johnniwinther): Avoid creating [CodeBuffer]s.
        List<jsAst.Expression> parts = <jsAst.Expression>[];
        for (LibraryElement library in Elements.sortedByPosition(libraries)) {
          parts.add(generateLibraryDescriptor(library, fragment));
          descriptors.remove(library);
        }

        outputs[outputUnit] = new jsAst.ArrayInitializer(parts);
      }
    }

    return outputs;
  }

  void finalizeTokensInAst(
      jsAst.Program main, Iterable<jsAst.Program> deferredParts) {
    jsAst.TokenCounter counter = new jsAst.TokenCounter();
    counter.countTokens(main);
    deferredParts.forEach(counter.countTokens);
    task.metadataCollector.finalizeTokens();
    if (backend.namer is jsAst.TokenFinalizer) {
      var finalizer = backend.namer;
      finalizer.finalizeTokens();
    }
  }

  int emitProgram(ProgramBuilder programBuilder) {
    Program program =
        programBuilder.buildProgram(storeFunctionTypesInMetadata: true);

    outputStaticNonFinalFieldLists =
        programBuilder.collector.outputStaticNonFinalFieldLists;
    outputLibraryLists = programBuilder.collector.outputLibraryLists;
    typedefsNeededForReflection =
        programBuilder.collector.typedefsNeededForReflection;

    assembleProgram(program);

    // Construct the ASTs for all deferred output units.
    Map<OutputUnit, jsAst.Program> deferredParts =
        buildOutputAstForDeferredCode(program);

    Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens =
        new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables(
            deferredParts.keys, deferredParts.keys.map((OutputUnit unit) {
      return new _DeferredOutputUnitHash(unit);
    }));

    jsAst.Program mainOutput =
        buildOutputAstForMain(program, deferredHashTokens);

    finalizeTokensInAst(mainOutput, deferredParts.values);

    // Emit deferred units first, so we have their hashes.
    // Map from OutputUnit to a hash of its content. The hash uniquely
    // identifies the code of the output-unit. It does not include
    // boilerplate JS code, like the sourcemap directives or the hash
    // itself.
    Map<OutputUnit, String> deferredLoadHashes =
        emitDeferredOutputUnits(deferredParts);

    deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) {
      token.setHash(deferredLoadHashes[key]);
    });
    emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput);

    if (backend.requiresPreamble && !backend.htmlLibraryIsLoaded) {
      reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
    }
    // Return the total program size.
    return outputBuffers.values.fold(0, (a, b) => a + b.length);
  }

  String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) {
    if (sourceMapUri != null && fileUri != null) {
      String sourceMapFileName = relativize(fileUri, sourceMapUri, false);
      return '''

//# sourceMappingURL=$sourceMapFileName
''';
    }
    return '';
  }

  ClassBuilder getElementDescriptor(Element element, Fragment fragment) {
    Element owner = element.library;
    if (!element.isLibrary &&
        !element.isTopLevel &&
        !backend.isNative(element)) {
      // For static (not top level) elements, record their code in a buffer
      // specific to the class. For now, not supported for native classes and
      // native elements.
      ClassElement cls = element.enclosingClassOrCompilationUnit.declaration;
      if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) &&
          !backend.isNative(cls) &&
          compiler.deferredLoadTask.outputUnitForElement(element) ==
              compiler.deferredLoadTask.outputUnitForElement(cls)) {
        owner = cls;
      }
    }
    if (owner == null) {
      reporter.internalError(element, 'Owner is null.');
    }
    return elementDescriptors
        .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>())
        .putIfAbsent(owner, () {
      return new ClassBuilder(owner, namer, owner.isClass);
    });
  }

  /// Emits support-code for deferred loading into [output].
  jsAst.Statement buildDeferredBoilerPlate(
      Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
    List<jsAst.Statement> parts = <jsAst.Statement>[];

    parts.add(js.statement(
        '''
        {
          // Function for checking if a hunk is loaded given its hash.
          #isHunkLoaded = function(hunkHash) {
            return !!$deferredInitializers[hunkHash];
          };
          #deferredInitialized = new Object(null);
          // Function for checking if a hunk is initialized given its hash.
          #isHunkInitialized = function(hunkHash) {
            return #deferredInitialized[hunkHash];
          };
          // Function for initializing a loaded hunk, given its hash.
          #initializeLoadedHunk = function(hunkHash) {
            $deferredInitializers[hunkHash](
            #globalsHolder, ${namer.staticStateHolder});
            #deferredInitialized[hunkHash] = true;
          };
        }
        ''',
        {
          "globalsHolder": globalsHolder,
          "isHunkLoaded":
              generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED),
          "isHunkInitialized":
              generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_INITIALIZED),
          "initializeLoadedHunk": generateEmbeddedGlobalAccess(
              embeddedNames.INITIALIZE_LOADED_HUNK),
          "deferredInitialized":
              generateEmbeddedGlobalAccess(embeddedNames.DEFERRED_INITIALIZED)
        }));

    // Write a javascript mapping from Deferred import load ids (derrived
    // from the import prefix.) to a list of lists of uris of hunks to load,
    // and a corresponding mapping to a list of hashes used by
    // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED.
    Map<String, List<jsAst.LiteralString>> deferredLibraryUris =
        new Map<String, List<jsAst.LiteralString>>();
    Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes =
        new Map<String, List<_DeferredOutputUnitHash>>();
    compiler.deferredLoadTask.hunksToLoad
        .forEach((String loadId, List<OutputUnit> outputUnits) {
      List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>();
      List<_DeferredOutputUnitHash> hashes =
          new List<_DeferredOutputUnitHash>();
      deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>();
      for (OutputUnit outputUnit in outputUnits) {
        uris.add(
            js.escapedString(backend.deferredPartFileName(outputUnit.name)));
        hashes.add(deferredLoadHashes[outputUnit]);
      }

      deferredLibraryUris[loadId] = uris;
      deferredLibraryHashes[loadId] = hashes;
    });

    void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) {
      List<jsAst.Property> properties = new List<jsAst.Property>();
      mapping.forEach((String key, List<jsAst.Expression> values) {
        properties.add(new jsAst.Property(
            js.escapedString(key), new jsAst.ArrayInitializer(values)));
      });
      jsAst.Node initializer =
          new jsAst.ObjectInitializer(properties, isOneLiner: true);

      jsAst.Node globalName = generateEmbeddedGlobalAccess(name);
      parts.add(js.statement("# = #", [globalName, initializer]));
    }

    emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris);
    emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, deferredLibraryHashes);

    return new jsAst.Block(parts);
  }

  Map<OutputUnit, jsAst.Program> buildOutputAstForDeferredCode(
      Program program) {
    if (!program.isSplit) return const <OutputUnit, jsAst.Program>{};

    Map<OutputUnit, jsAst.Program> result =
        new Map<OutputUnit, jsAst.Program>();

    Map<OutputUnit, jsAst.Expression> deferredAsts =
        buildDescriptorsForOutputUnits(program);

    for (Fragment fragment in program.deferredFragments) {
      OutputUnit outputUnit = fragment.outputUnit;
      jsAst.Expression libraryDescriptor = deferredAsts[outputUnit];
      List<jsAst.Statement> body = <jsAst.Statement>[];

      // No renaming in the top-level function to save the locals for the
      // nested context where they will be used more.
      body.add(js.comment("/* ::norenaming:: "));

      for (String globalObject in Namer.reservedGlobalObjectNames) {
        body.add(js.statement('var #object = #globalsHolder.#object;',
            {'globalsHolder': globalsHolder, 'object': globalObject}));
      }
      body
        ..add(js.statement('var init = #globalsHolder.init;',
            {'globalsHolder': globalsHolder}))
        ..add(js.statement(
            'var $setupProgramName = '
            '#globalsHolder.$setupProgramName;',
            {'globalsHolder': globalsHolder}))
        ..add(js.statement(
            'var ${namer.isolateName} = '
            '#globalsHolder.${namer.isolateName};',
            {'globalsHolder': globalsHolder}));
      String typesAccess =
          generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
      if (libraryDescriptor != null) {
        // The argument to reflectionDataParser is assigned to a temporary
        // 'dart' so that 'dart.' will appear as the prefix to dart methods
        // in stack traces and profile entries.
        body.add(js.statement('var dart = #', libraryDescriptor));

        if (compiler.options.useContentSecurityPolicy) {
          body.add(buildCspPrecompiledFunctionFor(outputUnit));
        }
        body.add(
            js.statement('$setupProgramName(dart, ${typesAccess}.length);'));
      }

      body
        ..add(buildMetadata(program, outputUnit))
        ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
            '${namer.deferredTypesName});'));

      body.add(
          buildCompileTimeConstants(fragment.constants, isMainFragment: false));
      body.add(buildStaticNonFinalFieldInitializations(outputUnit));
      body.add(buildLazilyInitializedStaticFields(
          fragment.staticLazilyInitializedFields,
          isMainFragment: false));

      List<jsAst.Statement> statements = <jsAst.Statement>[];

      statements
        ..add(buildGeneratedBy())
        ..add(buildDeferredHeader())
        ..add(js.statement(
            '${deferredInitializers}.current = '
            """function (#, ${namer.staticStateHolder}) {
                                  #
                                }
                             """,
            [globalsHolder, body]));

      result[outputUnit] = new jsAst.Program(statements);
    }

    return result;
  }

  /// Returns a map from OutputUnit to a hash of its content. The hash uniquely
  /// identifies the code of the output-unit. It does not include
  /// boilerplate JS code, like the sourcemap directives or the hash
  /// itself.
  Map<OutputUnit, String> emitDeferredOutputUnits(
      Map<OutputUnit, jsAst.Program> outputAsts) {
    Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>();

    for (OutputUnit outputUnit in outputAsts.keys) {
      List<CodeOutputListener> outputListeners = <CodeOutputListener>[];
      Hasher hasher = new Hasher();
      outputListeners.add(hasher);

      LineColumnCollector lineColumnCollector;
      if (generateSourceMap) {
        lineColumnCollector = new LineColumnCollector();
        outputListeners.add(lineColumnCollector);
      }

      String partPrefix =
          backend.deferredPartFileName(outputUnit.name, addExtension: false);
      CodeOutput output = new StreamCodeOutput(
          compiler.outputProvider(partPrefix, 'part.js'), outputListeners);

      outputBuffers[outputUnit] = output;

      output.addBuffer(jsAst.createCodeBuffer(outputAsts[outputUnit], compiler,
          monitor: compiler.dumpInfoTask));

      // Make a unique hash of the code (before the sourcemaps are added)
      // This will be used to retrieve the initializing function from the global
      // variable.
      String hash = hasher.getHash();

      output.add('$N${deferredInitializers}["$hash"]$_=$_'
          '${deferredInitializers}.current$N');

      if (generateSourceMap) {
        Uri mapUri, partUri;
        Uri sourceMapUri = compiler.options.sourceMapUri;
        Uri outputUri = compiler.options.outputUri;

        String partName = "$partPrefix.part";

        if (sourceMapUri != null) {
          String mapFileName = partName + ".js.map";
          List<String> mapSegments = sourceMapUri.pathSegments.toList();
          mapSegments[mapSegments.length - 1] = mapFileName;
          mapUri =
              compiler.options.sourceMapUri.replace(pathSegments: mapSegments);
        }

        if (outputUri != null) {
          String partFileName = partName + ".js";
          List<String> partSegments = outputUri.pathSegments.toList();
          partSegments[partSegments.length - 1] = partFileName;
          partUri =
              compiler.options.outputUri.replace(pathSegments: partSegments);
        }

        output.add(generateSourceMapTag(mapUri, partUri));
        output.close();
        outputSourceMap(output, lineColumnCollector, partName, mapUri, partUri);
      } else {
        output.close();
      }

      hunkHashes[outputUnit] = hash;
    }
    return hunkHashes;
  }

  jsAst.Comment buildGeneratedBy() {
    List<String> options = [];
    if (compiler.commonElements.mirrorsLibrary != null) options.add('mirrors');
    if (compiler.options.useContentSecurityPolicy) options.add("CSP");
    return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", ")));
  }

  void outputSourceMap(
      CodeOutput output, LineColumnProvider lineColumnProvider, String name,
      [Uri sourceMapUri, Uri fileUri]) {
    if (!generateSourceMap) return;
    // Create a source file for the compilation output. This allows using
    // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
    SourceMapBuilder sourceMapBuilder =
        new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider);
    output.forEachSourceLocation(sourceMapBuilder.addMapping);
    String sourceMap = sourceMapBuilder.build();
    compiler.outputProvider(name, 'js.map')
      ..add(sourceMap)
      ..close();
  }

  void outputDeferredMap() {
    Map<String, dynamic> mapping = new Map<String, dynamic>();
    // Json does not support comments, so we embed the explanation in the
    // data.
    mapping["_comment"] = "This mapping shows which compiled `.js` files are "
        "needed for a given deferred library import.";
    mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
    compiler.outputProvider(
        compiler.options.deferredMapUri.path, 'deferred_map')
      ..add(const JsonEncoder.withIndent("  ").convert(mapping))
      ..close();
  }

  void invalidateCaches() {
    if (!compiler.options.hasIncrementalSupport) return;
    if (cachedElements.isEmpty) return;
    for (Element element in backend.codegenEnqueuer.newlyEnqueuedElements) {
      if (element.isInstanceMember) {
        cachedClassBuilders.remove(element.enclosingClass);

        nativeEmitter.cachedBuilders.remove(element.enclosingClass);
      }
    }
  }
}
