// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:collection';
import '../../common_elements.dart' show ElementEnvironment;
import '../../deferred_load/deferred_load.dart'
    show ImportDescription, OutputUnit, OutputUnitData, deferredPartFileName;
import '../../elements/entities.dart';
import '../../js/js.dart' as js;
import '../../options.dart';
import '../model.dart';

/// This file contains a number of abstractions used by dart2js for emitting and
/// merging deferred fragments.
///
/// The initial deferred loading algorithm breaks a program up into multiple
/// [OutputUnits] where each [OutputUnit] represents part of the user's
/// program. [OutputUnits] are represented by a unique intersection of imports
/// known as an import set. Thus, each [OutputUnit] is a node in a deferred
/// graph. Edges in this graph are dependencies between [OutputUnits].
///
/// [OutputUnits] have a notion of successors and predecessors, that is a
/// successor to an [OutputUnit] is an [OutputUnit] that must be loaded first. A
/// predecessor to an [OutputUnit] is an [OutputUnit] that must be loaded later.
///
/// To load some given deferred library, a list of [OutputUnits] must be loaded
/// in the correct order, with their successors loaded first, then the given
/// [OutputUnit], then the [OutputUnits] predecessors.
///
/// To give a concrete example, say our graph looks like:
///    {a}   {b}   {c}
///
///     {a, b} {b, c}
///
///       {a, b, c}
///
/// Where each set above is the import set of an [OutputUnit]. We say that
/// {a}, {b}, and {c} are root [OutputUnits], i.e. [OutputUnits] with no
/// predecessors, and {a, b, c} is a leaf [OutputUnit], i.e. [OutputUnits]
/// with no successors.
///
/// We then have three load lists:
///   a: {a, b, c}, {a, b}, {a}
///   b: {a, b, c}, {a, b}, {b, c}, {b}
///   c: {a, b, c}, {b, c}, {c}
///
/// In all 3 load lists, {a, b, c} must be loaded first. All of the other
/// [OutputUnits] are predecessors of {a, b, c}. {a, b, c} is a successor to all
/// other [OutputUnits].
///
/// However, the dart2js deferred loading algorithm generates a very granular
/// sparse graph of [OutputUnits] and in many cases it is desireable to coalesce
/// smaller [OutputUnits] together into larger chunks of code to reduce the
/// number of files which have to be sent to the client. To do this
/// cleanly, we use various abstractions to merge [OutputUnits].
///
/// First, we emit the code for each [OutputUnit] into an [EmittedOutputUnit].
/// An [EmittedOutputUnit] is the Javascript representation of an [OutputUnit].
/// [EmittedOutputUnits] map 1:1 to [OutputUnits].
///
/// We wrap each [EmittedOutputUnit] in a [PreFragment], which is just a wrapper
/// to facilitate merging of [EmittedOutputUnits]. Then, we run a merge
/// algorithm on these [PreFragments], merging them together until some
/// threshold.
///
/// Once we are finished merging [PreFragments], we must now decide on their
/// final representation in Javascript.
///
/// Depending on the results of the merge, we chose one of two representations.
/// For example, say we merge {a, b} and {a} into {a, b}+{a}. In this case our
/// new load lists look like:
///
///   a: {a, b, c}, {a, b}+{a}
///   b: {a, b, c}, {a, b}+{a}, {b, c}, {b}
///   c: {a, b, c}, {b, c}, {c}
///
/// This adds a bit of extra code to the 'b' load list, but otherwise there are
/// no problems. In this case, we will interleave [EmittedOutputUnits] into a
/// single [CodeFragment], with a single top level initialization function. This
/// approach results in lower overhead, because the runtime can initialize the
/// {a, b}+{a} [CodeFragment] with a single invocation of a top level function.
///
/// Ideally we would interleave all [EmittedOutputUnits] in each [PreFragment]
/// into a single [CodeFragment]. We would then write this single
/// [CodeFragment] into a single [FinalizedFragment], where a
/// [FinalizedFragment] is just an abstraction representing a single file on
/// disk. Unfortunately this is not always possible to do efficiently.
///
/// Specifically, lets say we decide to merge {a} and {c} into {a}+{c}
/// In this case, our load lists now look like:
///
///   a: {a, b, c}, {a, b}, {a}+{c}
///   b: {a, b, c}, {a, b}, {b, c}, {b}
///   c: {a, b, c}, {b, c}, {a}+{c}
///
/// Now, load lists 'a' and 'c' are invalid. Specifically, load list 'a' is
/// missing {c}'s dependency {b, c} and load list 'c' is missing {a}'s
/// dependency {a, b}. We could bloat both load lists with the necessary
/// dependencies, but this would negate any performance benefit from
/// interleaving.
///
/// Instead, when this happens we emit {a} and {c} into separate
/// [CodeFragments], with separate top level initalization functions that are
/// only called when the necessary dependencies for initialization are
/// present. These [CodeFragments] end up in a single [FinalizedFragment].
/// While this approach doesn't have the performance benefits of
/// interleaving, it at least reduces the total number of files which need to be
/// sent to the client.

class EmittedOutputUnit {
  final Fragment fragment;
  final OutputUnit outputUnit;
  final List<Library> libraries;
  final js.Statement classPrototypes;
  final js.Statement closurePrototypes;
  final js.Statement inheritance;
  final js.Statement methodAliases;
  final js.Statement tearOffs;
  final js.Statement constants;
  final js.Statement typeRules;
  final js.Statement variances;
  final js.Statement staticNonFinalFields;
  final js.Statement lazyInitializers;
  final js.Statement nativeSupport;

  EmittedOutputUnit(
      this.fragment,
      this.outputUnit,
      this.libraries,
      this.classPrototypes,
      this.closurePrototypes,
      this.inheritance,
      this.methodAliases,
      this.tearOffs,
      this.constants,
      this.typeRules,
      this.variances,
      this.staticNonFinalFields,
      this.lazyInitializers,
      this.nativeSupport);

  CodeFragment toCodeFragment(Program program) {
    return CodeFragment(
        [fragment],
        [outputUnit],
        libraries,
        classPrototypes,
        closurePrototypes,
        inheritance,
        methodAliases,
        tearOffs,
        constants,
        typeRules,
        variances,
        staticNonFinalFields,
        lazyInitializers,
        nativeSupport,
        program.metadataTypesForOutputUnit(outputUnit));
  }
}

class PreFragment {
  final String outputFileName;
  final List<EmittedOutputUnit> emittedOutputUnits = [];
  final Set<PreFragment> successors = {};
  final Set<PreFragment> predecessors = {};
  FinalizedFragment finalizedFragment;
  int size = 0;
  // TODO(joshualitt): interleave dynamically when it makes sense.
  bool shouldInterleave = false;

  PreFragment(
      this.outputFileName, EmittedOutputUnit emittedOutputUnit, this.size) {
    emittedOutputUnits.add(emittedOutputUnit);
  }

  PreFragment mergeAfter(PreFragment that) {
    assert(this != that);
    this.emittedOutputUnits.addAll(that.emittedOutputUnits);
    this.successors.remove(that);
    this.predecessors.remove(that);
    that.successors.forEach((fragment) {
      if (fragment == this) return;
      this.successors.add(fragment);
      fragment.predecessors.remove(that);
      fragment.predecessors.add(this);
    });
    that.predecessors.forEach((fragment) {
      if (fragment == this) return;
      this.predecessors.add(fragment);
      fragment.successors.remove(that);
      fragment.successors.add(this);
    });
    that.clearAll();
    this.size += that.size;
    return this;
  }

  /// Interleaves the [EmittedOutputUnits] into a single [CodeFragment].
  CodeFragment interleaveEmittedOutputUnits(Program program) {
    var seedEmittedOutputUnit = emittedOutputUnits.first;
    if (emittedOutputUnits.length == 1) {
      return seedEmittedOutputUnit.toCodeFragment(program);
    } else {
      var seedOutputUnit = seedEmittedOutputUnit.outputUnit;
      List<Fragment> fragments = [];
      List<Library> libraries = [];
      List<OutputUnit> outputUnits = [seedOutputUnit];
      List<js.Statement> classPrototypes = [];
      List<js.Statement> closurePrototypes = [];
      List<js.Statement> inheritance = [];
      List<js.Statement> methodAliases = [];
      List<js.Statement> tearOffs = [];
      List<js.Statement> constants = [];
      List<js.Statement> typeRules = [];
      List<js.Statement> variances = [];
      List<js.Statement> staticNonFinalFields = [];
      List<js.Statement> lazyInitializers = [];
      List<js.Statement> nativeSupport = [];
      for (var emittedOutputUnit in emittedOutputUnits) {
        var thatOutputUnit = emittedOutputUnit.outputUnit;
        if (seedOutputUnit != thatOutputUnit) {
          program.mergeOutputUnitMetadata(seedOutputUnit, thatOutputUnit);
          outputUnits.add(thatOutputUnit);
          fragments.add(emittedOutputUnit.fragment);
        }
        libraries.addAll(emittedOutputUnit.libraries);
        classPrototypes.add(emittedOutputUnit.classPrototypes);
        closurePrototypes.add(emittedOutputUnit.closurePrototypes);
        inheritance.add(emittedOutputUnit.inheritance);
        methodAliases.add(emittedOutputUnit.methodAliases);
        tearOffs.add(emittedOutputUnit.tearOffs);
        constants.add(emittedOutputUnit.constants);
        typeRules.add(emittedOutputUnit.typeRules);
        variances.add(emittedOutputUnit.variances);
        staticNonFinalFields.add(emittedOutputUnit.staticNonFinalFields);
        lazyInitializers.add(emittedOutputUnit.lazyInitializers);
        nativeSupport.add(emittedOutputUnit.nativeSupport);
      }
      return CodeFragment(
          fragments,
          outputUnits,
          libraries,
          js.Block(classPrototypes),
          js.Block(closurePrototypes),
          js.Block(inheritance),
          js.Block(methodAliases),
          js.Block(tearOffs),
          js.Block(constants),
          js.Block(typeRules),
          js.Block(variances),
          js.Block(staticNonFinalFields),
          js.Block(lazyInitializers),
          js.Block(nativeSupport),
          program.metadataTypesForOutputUnit(seedOutputUnit));
    }
  }

  /// Bundles [EmittedOutputUnits] into multiple [CodeFragments].
  List<CodeFragment> bundleEmittedOutputUnits(Program program) {
    List<CodeFragment> codeFragments = [];
    for (var emittedOutputUnit in emittedOutputUnits) {
      codeFragments.add(emittedOutputUnit.toCodeFragment(program));
    }
    return codeFragments;
  }

  /// Finalizes this [PreFragment] into a single [FinalizedFragment] by either
  /// interleaving [EmittedOutputUnits] into a single [CodeFragment] or by
  /// bundling [EmittedOutputUnits] into multiple [CodeFragments].
  FinalizedFragment finalize(
      Program program,
      Map<OutputUnit, CodeFragment> outputUnitMap,
      Map<CodeFragment, FinalizedFragment> codeFragmentMap) {
    assert(finalizedFragment == null);
    List<CodeFragment> codeFragments = shouldInterleave
        ? [interleaveEmittedOutputUnits(program)]
        : bundleEmittedOutputUnits(program);
    finalizedFragment = FinalizedFragment(outputFileName, codeFragments);
    codeFragments.forEach((codeFragment) {
      codeFragmentMap[codeFragment] = finalizedFragment;
      codeFragment.outputUnits.forEach((outputUnit) {
        outputUnitMap[outputUnit] = codeFragment;
      });
    });
    return finalizedFragment;
  }

  @override
  String toString() {
    // This is not an efficient operation and should only be used for debugging.
    var successors =
        this.successors.map((fragment) => fragment.debugName()).join(',');
    var predecessors =
        this.predecessors.map((fragment) => fragment.debugName()).join(',');
    var name = debugName();
    return 'PreFragment(fragments=[$name], successors=[$successors], '
        'predecessors=[$predecessors])';
  }

  String debugName() {
    var outputUnitStrings = [];
    for (var emittedOutputUnit in emittedOutputUnits) {
      var importString = [];
      for (var import in emittedOutputUnit.outputUnit.imports) {
        importString.add(import.name);
      }
      outputUnitStrings.add('{${importString.join(', ')}}');
    }
    return "${outputUnitStrings.join('+')}";
  }

  /// Clears all [PreFragment] data structure and zeros out the size. Should be
  /// used only after merging to GC internal data structures.
  void clearAll() {
    emittedOutputUnits.clear();
    successors.clear();
    predecessors.clear();
    size = 0;
  }
}

class CodeFragment {
  final List<Fragment> fragments;
  final List<OutputUnit> outputUnits;
  final List<Library> libraries;
  final js.Statement classPrototypes;
  final js.Statement closurePrototypes;
  final js.Statement inheritance;
  final js.Statement methodAliases;
  final js.Statement tearOffs;
  final js.Statement constants;
  final js.Statement typeRules;
  final js.Statement variances;
  final js.Statement staticNonFinalFields;
  final js.Statement lazyInitializers;
  final js.Statement nativeSupport;
  final js.Expression deferredTypes;

  CodeFragment(
      this.fragments,
      this.outputUnits,
      this.libraries,
      this.classPrototypes,
      this.closurePrototypes,
      this.inheritance,
      this.methodAliases,
      this.tearOffs,
      this.constants,
      this.typeRules,
      this.variances,
      this.staticNonFinalFields,
      this.lazyInitializers,
      this.nativeSupport,
      this.deferredTypes);

  bool isEmptyStatement(js.Statement statement) {
    if (statement is js.Block) {
      return statement.statements.isEmpty;
    }
    return statement is js.EmptyStatement;
  }

  bool get isEmpty {
    // 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.
    // TODO(joshualitt): Currently, we ignore [typeRules] when determining
    // emptiness because the type rules never seem to be empty.
    return isEmptyStatement(classPrototypes) &&
        isEmptyStatement(closurePrototypes) &&
        isEmptyStatement(inheritance) &&
        isEmptyStatement(methodAliases) &&
        isEmptyStatement(tearOffs) &&
        isEmptyStatement(constants) &&
        isEmptyStatement(staticNonFinalFields) &&
        isEmptyStatement(lazyInitializers) &&
        isEmptyStatement(nativeSupport);
  }

  @override
  String toString() {
    List<String> outputUnitStrings = [];
    for (var outputUnit in outputUnits) {
      List<String> importStrings = [];
      for (var import in outputUnit.imports) {
        importStrings.add(import.name);
      }
      outputUnitStrings.add('{${importStrings.join(', ')}}');
    }
    return outputUnitStrings.join('+');
  }

  OutputUnit get canonicalOutputUnit => outputUnits.first;
}

class FinalizedFragment {
  final String outputFileName;
  final List<CodeFragment> codeFragments;

  FinalizedFragment(this.outputFileName, this.codeFragments);

  // The 'main' [OutputUnit] for this [FinalizedFragment].
  // TODO(joshualitt): Refactor this to more clearly disambiguate between
  // [OutputUnits](units of deferred merging), fragments(units of emitted code),
  // and files.
  OutputUnit get canonicalOutputUnit => codeFragments.first.canonicalOutputUnit;

  @override
  String toString() {
    List<String> strings = [];
    for (var codeFragment in codeFragments) {
      strings.add(codeFragment.toString());
    }
    return 'FinalizedFragment([${strings.join(', ')}])';
  }
}

class _Partition {
  int size = 0;
  List<PreFragment> fragments = [];
  bool isClosed = false;

  void add(PreFragment that) {
    size += that.size;
    fragments.add(that);
  }
}

class FragmentMerger {
  final CompilerOptions _options;
  final ElementEnvironment _elementEnvironment;
  final OutputUnitData outputUnitData;
  int totalSize = 0;

  FragmentMerger(this._options, this._elementEnvironment, this.outputUnitData);

  // Converts a map of (loadId, List<OutputUnit>) to two maps.
  // The first is a map of (loadId, List<FinalizedFragment>), which is used to
  // compute which files need to be loaded for a given loadId.
  // The second is a map of (loadId, List<CodeFragment>) which is used to
  // compute which CodeFragments need to be loaded for a given loadId.
  void computeFragmentsToLoad(
      Map<String, List<OutputUnit>> outputUnitsToLoad,
      Map<OutputUnit, CodeFragment> outputUnitMap,
      Map<CodeFragment, FinalizedFragment> codeFragmentMap,
      Set<OutputUnit> omittedOutputUnits,
      Map<String, List<CodeFragment>> codeFragmentsToLoad,
      Map<String, List<FinalizedFragment>> finalizedFragmentsToLoad) {
    outputUnitsToLoad.forEach((loadId, outputUnits) {
      Set<CodeFragment> uniqueCodeFragments = {};
      Set<FinalizedFragment> uniqueFinalizedFragments = {};
      List<FinalizedFragment> finalizedFragments = [];
      List<CodeFragment> codeFragments = [];
      for (var outputUnit in outputUnits) {
        if (omittedOutputUnits.contains(outputUnit)) continue;
        var codeFragment = outputUnitMap[outputUnit];
        if (uniqueCodeFragments.add(codeFragment)) {
          codeFragments.add(codeFragment);
        }
        var finalizedFragment = codeFragmentMap[codeFragment];
        if (uniqueFinalizedFragments.add(finalizedFragment)) {
          finalizedFragments.add(finalizedFragment);
        }
      }
      codeFragmentsToLoad[loadId] = codeFragments;
      finalizedFragmentsToLoad[loadId] = finalizedFragments;
    });
  }

  /// Given a list of OutputUnits sorted by their import entites,
  /// returns a map of all the direct edges between output units.
  Map<OutputUnit, Set<OutputUnit>> createDirectEdges(
      List<OutputUnit> allOutputUnits) {
    Map<OutputUnit, Set<OutputUnit>> backEdges = {};
    for (int i = 0; i < allOutputUnits.length; i++) {
      var a = allOutputUnits[i];
      var aImports = a.imports;
      for (int j = i + 1; j < allOutputUnits.length; j++) {
        var b = allOutputUnits[j];
        if (b.imports.containsAll(aImports)) {
          backEdges[b] ??= {};

          // Remove transitive edges from nodes that will reach 'b' from the
          // edge we just added.
          // Note: Because we add edges in order (starting from the smallest
          // sets) we always add transitive edges before the last direct edge.
          backEdges[b].removeWhere((c) => aImports.containsAll(c.imports));

          // Create an edge to denote that 'b' must be loaded before 'a'.
          backEdges[b].add(a);
        }
      }
    }

    Map<OutputUnit, Set<OutputUnit>> forwardEdges = {};
    backEdges.forEach((b, edges) {
      for (var a in edges) {
        (forwardEdges[a] ??= {}).add(b);
      }
    });
    return forwardEdges;
  }

  /// Attachs predecessors and successors to each PreFragment.
  /// Expects outputUnits to be sorted.
  void attachDependencies(
      List<OutputUnit> outputUnits, List<PreFragment> preDeferredFragments) {
    // Create a map of OutputUnit to Fragment.
    Map<OutputUnit, PreFragment> outputUnitMap = {};
    for (var preFragment in preDeferredFragments) {
      var outputUnit = preFragment.emittedOutputUnits.single.outputUnit;
      outputUnitMap[outputUnit] = preFragment;
      totalSize += preFragment.size;
    }

    // Get a list of direct edges and then attach them to PreFragments.
    var allEdges = createDirectEdges(outputUnits);
    allEdges.forEach((outputUnit, edges) {
      var predecessor = outputUnitMap[outputUnit];
      for (var edge in edges) {
        var successor = outputUnitMap[edge];
        predecessor.successors.add(successor);
        successor.predecessors.add(predecessor);
      }
    });
  }

  /// Given a list of [PreFragments], returns a list of lists of [PreFragments]
  /// where each list represents a component in the graph.
  List<List<PreFragment>> separateComponents(
      List<PreFragment> preDeferredFragments) {
    List<List<PreFragment>> components = [];
    Set<PreFragment> visited = {};

    // Starting from each 'root' in the graph, use bfs to find a component.
    for (var preFragment in preDeferredFragments) {
      if (preFragment.predecessors.isEmpty && visited.add(preFragment)) {
        List<PreFragment> component = [];
        var queue = Queue<PreFragment>();
        queue.add(preFragment);
        while (queue.isNotEmpty) {
          var preFragment = queue.removeFirst();
          component.add(preFragment);
          preFragment.predecessors.where(visited.add).forEach(queue.add);
          preFragment.successors.where(visited.add).forEach(queue.add);
        }

        // Sort the fragments in the component so they will be in a canonical
        // order.
        component.sort((a, b) {
          return a.emittedOutputUnits.single.outputUnit
              .compareTo(b.emittedOutputUnits.single.outputUnit);
        });
        components.add(component);
      }
    }
    return components;
  }

  /// A trivial greedy merge that uses the sorted order of the output units to
  /// merge contiguous runs of fragments without creating cycles.
  /// ie, if our sorted output units look like:
  ///   {a}, {b}, {c}, {a, b}, {b, c}, {a, b, c},
  /// Assuming singletons have size 3, doubles have size 2, and triples have
  /// size 1, total size would be 14. If we want 3 fragments, we have an ideal
  /// fragment size of 5. Our final partitions would look like:
  ///   {a}, {b}, {c}+{a, b}, {b, c}+{a, b, c}.
  List<PreFragment> mergeFragments(List<PreFragment> preDeferredFragments) {
    var components = separateComponents(preDeferredFragments);
    int desiredNumberOfFragment = _options.mergeFragmentsThreshold;
    int idealFragmentSize = (totalSize / desiredNumberOfFragment).ceil();
    List<_Partition> partitions = [];
    void add(PreFragment next) {
      // Create a new partition if the current one grows too large, otherwise
      // just add to the most recent partition.
      if (partitions.isEmpty ||
          partitions.last.isClosed ||
          partitions.last.size + next.size > idealFragmentSize) {
        partitions.add(_Partition());
      }
      partitions.last.add(next);
    }

    // Greedily group fragments into partitions, but only within each component.
    for (var component in components) {
      component.forEach(add);
      partitions.last.isClosed = true;
    }

    // Reduce fragments by merging fragments with fewer imports into fragments
    // with more imports.
    List<PreFragment> merged = [];
    for (var partition in partitions) {
      merged.add(partition.fragments.reduce((a, b) => b.mergeAfter(a)));
    }
    return merged;
  }

  /// Computes load lists using a list of sorted OutputUnits.
  Map<String, List<OutputUnit>> computeOutputUnitsToLoad(
      List<OutputUnit> outputUnits) {
    // Sort the output units in descending order of the number of imports they
    // include.

    // The loading of the output units must be ordered because a superclass
    // needs to be initialized before its subclass.
    // But a class can only depend on another class in an output unit shared by
    // a strict superset of the imports:
    // By contradiction: Assume a class C in output unit shared by imports in
    // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit
    // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in
    // S1 not in S2. lib_s must depend on C, and then in turn on D. Therefore D
    // is not in the right output unit.
    List<OutputUnit> sortedOutputUnits = outputUnits.reversed.toList();

    Map<String, List<OutputUnit>> outputUnitsToLoad = {};
    for (var import in outputUnitData.deferredImportDescriptions.keys) {
      var loadId = outputUnitData.importDeferName[import];
      List<OutputUnit> loadList = [];
      for (var outputUnit in sortedOutputUnits) {
        assert(!outputUnit.isMainOutput);
        if (outputUnit.imports.contains(import)) {
          loadList.add(outputUnit);
        }
      }
      outputUnitsToLoad[loadId] = loadList;
    }
    return outputUnitsToLoad;
  }

  /// Returns a json-style map for describing what files that are loaded by a
  /// given deferred import.
  /// The mapping is structured as:
  /// library uri -> {"name": library name, "files": (prefix -> list of files)}
  /// Where
  ///
  /// - <library uri> is the import uri of the library making a deferred
  ///   import.
  /// - <library name> is the name of the library, or "<unnamed>" if it is
  ///   unnamed.
  /// - <prefix> is the `as` prefix used for a given deferred import.
  /// - <list of files> is a list of the filenames the must be loaded when that
  ///   import is loaded.
  /// TODO(joshualitt): the library name is unused and should be removed. This
  /// will be a breaking change.
  Map<String, Map<String, dynamic>> computeDeferredMap(
      Map<String, List<FinalizedFragment>> fragmentsToLoad) {
    Map<String, Map<String, dynamic>> mapping = {};

    outputUnitData.deferredImportDescriptions.keys
        .forEach((ImportEntity import) {
      var importDeferName = outputUnitData.importDeferName[import];
      List<FinalizedFragment> fragments = fragmentsToLoad[importDeferName];
      ImportDescription description =
          outputUnitData.deferredImportDescriptions[import];
      String getName(LibraryEntity library) {
        var name = _elementEnvironment.getLibraryName(library);
        return name == '' ? '<unnamed>' : name;
      }

      Map<String, dynamic> libraryMap = mapping.putIfAbsent(
          description.importingUri,
          () => {"name": getName(description.importingLibrary), "imports": {}});

      List<String> partFileNames = fragments
          .map((fragment) =>
              deferredPartFileName(_options, fragment.canonicalOutputUnit.name))
          .toList();
      libraryMap["imports"][importDeferName] = partFileNames;
    });
    return mapping;
  }
}
