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

library;

import 'dart:math' show max;

import 'package:js_shared/synced/async_status_codes.dart' as status_codes;

import '../common.dart';
import 'js.dart' as js;

/// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
/// (with dart-like semantics) to an equivalent function without these.
/// await-for is not handled and must be rewritten before. (Currently handled
/// in ssa/builder.dart).
///
/// When generating the input to this, special care must be taken that
/// parameters to sync* functions that are mutated in the body must be boxed.
/// (Currently handled in closure.dart).
///
/// Look at [rewriteFunction], [visitDartYield] and [visitAwait] for more
/// explanation.
abstract class AsyncRewriterBase extends js.NodeVisitor<Object?> {
  // Local variables are hoisted to the top of the function, so they are
  // collected here.
  List<js.VariableDeclaration> localVariables = [];

  Map<js.Node, int> continueLabels = {};
  Map<js.Node, int> breakLabels = {};

  /// The label of a finally part.
  Map<js.Block, int> finallyLabels = {};

  /// The label of the catch handler of a [js.Try] or a [js.Fun] or [js.Catch].
  ///
  /// These mark the points an error can be consumed.
  ///
  /// - The handler of a [js.Fun] is the outermost and will rethrow the error.
  /// - The handler of a [js.Try] will run the catch handler.
  /// - The handler of a [js.Catch] is a synthetic handler that ensures the
  ///   right finally blocks are run if an error is thrown inside a
  ///   catch-handler.
  Map<js.Node, int> handlerLabels = {};

  int? exitLabel;
  late int rethrowLabel;

  /// A stack of all (surrounding) jump targets.
  ///
  /// Jump targets are:
  ///
  /// * The function, signalling a return or uncaught throw.
  /// * Loops.
  /// * LabeledStatements (also used for 'continue' when attached to loops).
  /// * Try statements, for catch and finally handlers.
  /// * Catch handlers, when inside a catch-part of a try, the catch-handler is
  ///   used to associate with a synthetic handler that will ensure the right
  ///   finally blocks are visited.
  ///
  /// When jumping to a target it is necessary to visit all finallies that
  /// are on the way to target (i.e. more nested than the jump target).
  List<js.Node> jumpTargets = [];

  List<(String, String)> variableRenamings = [];

  late final PreTranslationAnalysis analysis;

  final String Function(String) safeVariableName;

  // All the <x>Name variables are names of JavaScript variables used in the
  // transformed code.

  /// Contains the result of an awaited expression, or a conditional or
  /// lazy boolean operator.
  ///
  /// For example a conditional expression is roughly translated like:
  /// [[cond ? a : b]]
  ///
  /// Becomes:
  ///
  /// while true { // outer while loop
  ///   switch (goto) { // Simulates goto
  ///     ...
  ///       goto = [[cond]] ? thenLabel : elseLabel
  ///       break;
  ///     case thenLabel:
  ///       result = [[a]];
  ///       goto = joinLabel;
  ///       break;
  ///     case elseLabel:
  ///       result = [[b]];
  ///     case joinLabel:
  ///       // Now the result of computing the condition is in result.
  ///     ....
  ///   }
  /// }
  ///
  /// It is a parameter to the [body] function, so that [awaitStatement] can
  /// call [body] with the result of an awaited Future.
  js.VariableUse get result => js.VariableUse(resultName);
  late final String resultName;

  /// A parameter to the [bodyName] function. Indicating if we are in success
  /// or error case.
  late final String errorCodeName;

  /// The inner function that is scheduled to do each await/yield,
  /// and called to do a new iteration for sync*.
  final js.Name bodyName;

  /// Used to simulate a goto.
  ///
  /// To "goto" a label, the label is assigned to this variable, and break out
  /// of the switch to take another iteration in the while loop. See [addGoto]
  js.VariableUse get goto => js.VariableUse(gotoName);
  late final String gotoName;

  /// Variable containing the label of the current error handler.
  js.VariableUse get handler => js.VariableUse(handlerName);
  late final String handlerName;

  /// Set to `true` if any of the switch statement labels is a handler. At the
  /// end of rewriting this is used to see if a shorter form of error handling
  /// can be used. The shorter form could be a change in the method boilerplate,
  /// in the state machine wrapper, or not implemented. [addErrorExit] can test
  /// this to elide the error exit handler when there are no other handlers, or
  /// set it to `true` if there is no shorter form.
  bool hasHandlerLabels = false;

  /// A stack of labels of finally blocks to visit, and the label to go to after
  /// the last.
  js.VariableUse get next => js.VariableUse(nextName);
  late final String nextName;

  /// The current returned value (a finally block may overwrite it).
  js.VariableUse get returnValue => js.VariableUse(returnValueName);
  late final String returnValueName;

  /// Stores a stack of the current set of errors when we are in the process of
  /// handling an error. Errors are pushed onto this stack when error handling
  /// begins and the current error is popped off when error handling ends. This
  /// prevents nested error handling from overwriting state.
  js.VariableUse get errorStack => js.VariableUse(errorStackName);
  late final String errorStackName;

  /// The label of the outer loop.
  ///
  /// Used if there are untransformed loops containing break or continues to
  /// targets outside the loop.
  late final String outerLabelName;

  /// If javascript `this` is used, it is accessed via this variable, in the
  /// [bodyName] function.
  js.VariableUse get self => js.VariableUse(selfName);
  late final String selfName;

  /// The rewritten code can take type arguments. These are added if needed.
  final List<String> typeArgumentNames = [];

  final DiagnosticReporter reporter;
  // For error reporting only.
  Spannable get spannable => _spannable ?? noLocationSpannable;
  final Spannable? _spannable;

  int _currentLabel = 0;

  // The highest temporary variable index currently in use.
  int currentTempVarIndex = 0;
  // The highest temporary variable index ever in use in this function.
  int tempVarHighWaterMark = 0;
  Map<int, js.VariableUse> tempVarNames = {};

  bool get isAsync => false;
  bool get isSyncStar => false;
  bool get isAsyncStar => false;

  AsyncRewriterBase(
    this.reporter,
    this._spannable,
    this.safeVariableName,
    this.bodyName,
  );

  /// Initialize names used by the subClass.
  void initializeNames();

  /// Main entry point.
  /// Rewrites a sync*/async/async* function to an equivalent normal function.
  ///
  /// [spannable] can be passed to have a location for error messages.
  js.Fun rewrite(
    js.Fun node,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
    js.JavaScriptNodeSourceInformation? exitSourceInformation,
  ) {
    analysis = PreTranslationAnalysis(unsupported);
    analysis.analyze(node);

    // To avoid name collisions with existing names, the fresh names are
    // generated after the analysis.
    resultName = freshName("result");
    errorCodeName = freshName("errorCode");
    gotoName = freshName("goto");
    handlerName = freshName("handler");
    nextName = freshName("next");
    returnValueName = freshName("returnValue");
    errorStackName = freshName("errorStack");
    outerLabelName = freshName("outer");
    selfName = freshName("self");
    // Initialize names specific to the subclass.
    initializeNames();

    return rewriteFunction(node, bodySourceInformation, exitSourceInformation);
  }

  js.Expression get currentErrorHandler {
    return js.number(
      handlerLabels[jumpTargets.lastWhere(
        (node) => handlerLabels[node] != null,
      )]!,
    );
  }

  int allocateTempVar() {
    assert(tempVarHighWaterMark >= currentTempVarIndex);
    currentTempVarIndex++;
    tempVarHighWaterMark = max(currentTempVarIndex, tempVarHighWaterMark);
    return currentTempVarIndex;
  }

  js.VariableUse useTempVar(int i) {
    return tempVarNames[i] ??= js.VariableUse(freshName("temp$i"));
  }

  /// Generates a variable name with [safeVariableName] based on [originalName]
  /// with a suffix to guarantee it does not collide with already used names.
  String freshName(String originalName) {
    String safeName = safeVariableName(originalName);
    String result = safeName;
    int counter = 1;
    while (analysis.usedNames.contains(result)) {
      result = "$safeName$counter";
      ++counter;
    }
    analysis.usedNames.add(result);
    return result;
  }

  List<js.Expression> processTypeArguments(List<js.Expression>? types) {
    if (types == null) {
      String name = freshName('type');
      typeArgumentNames.add(name);
      return [js.VariableUse(name)];
    }
    return types;
  }

  /// All the pieces are collected in this map, to create a switch with a case
  /// for each label.
  ///
  /// The order is important due to fall-through control flow, therefore the
  /// type is explicitly LinkedHashMap.
  Map<int, List<js.Statement>> labelledParts = {};

  /// Description of each label for readability of the non-minified output.
  Map<int, String> labelComments = {};

  /// True if the function has any try blocks containing await.
  bool hasTryBlocks = false;

  /// True if the traversion currently is inside a loop or switch for which
  /// [shouldTransform] is false.
  bool insideUntranslatedBreakable = false;

  /// True if a label is used to break to an outer switch-statement.
  bool hasJumpThoughOuterLabel = false;

  /// True if there is a catch-handler protected by a finally with no enclosing
  /// catch-handlers.
  bool needsRethrow = false;

  /// Buffer for collecting translated statements belonging to the same switch
  /// case.
  List<js.Statement> currentStatementBuffer = [];

  // Labels will become cases in the big switch expression, and `goto label`
  // is expressed by assigning to the switch key [gotoName] and breaking out of
  // the switch.

  int newLabel(String comment) {
    int result = _currentLabel++;
    labelComments[result] = comment;
    return result;
  }

  /// Begins outputting statements to a new buffer with label [label].
  ///
  /// Each buffer ends up as its own case part in the big state-switch.
  void beginLabel(int label) {
    assert(!labelledParts.containsKey(label));
    currentStatementBuffer = [];
    labelledParts[label] = currentStatementBuffer;
    addStatement(js.Comment(labelComments[label]!));
  }

  /// Returns a statement assigning to the variable named [gotoName].
  /// This should be followed by a break for the goto to be executed. Use
  /// [gotoWithBreak] or [addGoto] for this.
  js.Statement setGotoVariable(
    int label,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    return js.ExpressionStatement(
      js
          .js('# = #', [goto, js.number(label)])
          .withSourceInformation(sourceInformation),
    );
  }

  /// Returns a block that has a goto to [label] including the break.
  ///
  /// Also inserts a comment describing the label if available.
  js.Block gotoAndBreak(
    int label,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    List<js.Statement> statements = [];
    if (labelComments.containsKey(label)) {
      statements.add(js.Comment("goto ${labelComments[label]}"));
    }
    statements.add(setGotoVariable(label, sourceInformation));
    if (insideUntranslatedBreakable) {
      hasJumpThoughOuterLabel = true;
      statements.add(
        js.Break(outerLabelName).withSourceInformation(sourceInformation),
      );
    } else {
      statements.add(js.Break(null).withSourceInformation(sourceInformation));
    }
    return js.Block(statements);
  }

  /// Adds a goto to [label] including the break.
  ///
  /// Also inserts a comment describing the label if available.
  void addGoto(
    int label,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    if (labelComments.containsKey(label)) {
      addStatement(js.Comment("goto ${labelComments[label]}"));
    }
    addStatement(setGotoVariable(label, sourceInformation));

    addBreak(sourceInformation);
  }

  void addStatement(js.Statement node) {
    currentStatementBuffer.add(node);
  }

  void addExpressionStatement(js.Expression node) {
    addStatement(js.ExpressionStatement(node));
  }

  /// True if there is an await or yield in [node] or some subexpression.
  bool shouldTransform(js.Node? node) {
    return analysis.hasAwaitOrYield.contains(node);
  }

  Never unsupported(js.Node node) {
    throw UnsupportedError(
      "Node $node cannot be transformed by the await-sync transformer",
    );
  }

  Never unreachable(js.Node node) {
    reporter.internalError(spannable, "Internal error, trying to visit $node");
  }

  void visitStatement(js.Statement node) {
    node.accept(this);
  }

  /// Visits [node] to ensure its side effects are performed, but throwing away
  /// the result.
  ///
  /// If the return value of visiting [node] is an expression guaranteed to have
  /// no side effect, it is dropped.
  void visitExpressionIgnoreResult(js.Expression node) {
    // TODO(28763): Remove `<dynamic>` when issue 28763 is fixed.
    js.Expression result = node.accept<dynamic>(this)!;
    if (!(result is js.Literal || result is js.VariableUse)) {
      addExpressionStatement(result);
    }
  }

  js.Expression visitExpression(js.Expression node) {
    // TODO(28763): Remove `<dynamic>` when issue 28763 is fixed.
    return node.accept<dynamic>(this);
  }

  /// Calls [fn] with the value of evaluating [node1] and [node2].
  ///
  /// Both nodes are evaluated in order.
  ///
  /// If node2 must be transformed (see [shouldTransform]), then the evaluation
  /// of node1 is added to the current statement-list and the result is stored
  /// in a temporary variable. The evaluation of node2 is then free to emit
  /// statements without affecting the result of node1.
  ///
  /// This is necessary, because await or yield expressions have to emit
  /// statements, and these statements could affect the value of node1.
  ///
  /// For example:
  ///
  /// - _storeIfNecessary(someLiteral) returns someLiteral.
  /// - _storeIfNecessary(someVariable)
  ///   inserts: var tempX = someVariable
  ///   returns: tempX
  ///   where tempX is a fresh temporary variable.
  js.Expression _storeIfNecessary(js.Expression result) {
    // Note that RegExes, js.ArrayInitializer and js.ObjectInitializer are not
    // [js.Literal]s.
    if (result is js.Literal) return result;
    if (result is js.VariableUse) {
      if (result.name == selfName) return result;
    }

    js.Expression tempVar = useTempVar(allocateTempVar());
    addStatement(js.js.statement('# = #;', [tempVar, result]));
    return tempVar;
  }

  // TODO(sra): Many calls to this method use `store: false`, and could be
  // replaced with calls to `visitExpression`.
  T withExpression<T>(
    js.Expression node,
    T Function(js.Expression result) fn, {
    required bool store,
  }) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression visited = visitExpression(node);
    if (store) {
      visited = _storeIfNecessary(visited);
    }
    var result = fn(visited);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Calls [fn] with the result of evaluating [node]. Taking special care of
  /// property accesses.
  ///
  /// If [store] is true the result of evaluating [node] is stored in a
  /// temporary.
  ///
  /// We cannot rewrite `<receiver>.m()` to:
  ///
  ///     temp = <receiver>.m;
  ///     temp();
  ///
  /// Because this leaves `this` unbound in the call. But because of dart
  /// evaluation order we can write:
  ///
  ///     temp = <receiver>;
  ///     temp.m();
  ///
  js.Expression withCallTargetExpression(
    js.Expression node,
    js.Expression Function(js.Expression result) fn, {
    required bool store,
  }) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression visited = visitExpression(node);
    js.Expression? selector;
    js.Expression storedIfNeeded;
    if (store) {
      if (visited is js.PropertyAccess) {
        js.PropertyAccess propertyAccess = visited;
        selector = propertyAccess.selector;
        visited = propertyAccess.receiver;
      }
      storedIfNeeded = _storeIfNecessary(visited);
    } else {
      storedIfNeeded = visited;
    }
    js.Expression result;
    if (selector == null) {
      result = fn(storedIfNeeded);
    } else {
      result = fn(js.PropertyAccess(storedIfNeeded, selector));
    }
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Calls [fn] with the value of evaluating [node1] and [node2].
  ///
  /// If `shouldTransform(node2)` the first expression is stored in a temporary
  /// variable.
  ///
  /// This is because node1 must be evaluated before visiting node2,
  /// because the evaluation of an await or yield cannot be expressed as
  /// an expression, visiting node2 it will output statements that
  /// might have an influence on the value of node1.
  js.Expression withExpression2(
    js.Expression node1,
    js.Expression node2,
    js.Expression Function(js.Expression result1, js.Expression result2) fn,
  ) {
    int oldTempVarIndex = currentTempVarIndex;
    js.Expression r1 = visitExpression(node1);
    if (shouldTransform(node2)) {
      r1 = _storeIfNecessary(r1);
    }
    js.Expression r2 = visitExpression(node2);
    var result = fn(r1, r2);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Calls [fn] with the value of evaluating all [nodes].
  ///
  /// All results before the last node where `shouldTransform(node)` are stored
  /// in temporary variables.
  ///
  /// See more explanation on [withExpression2].
  T withExpressions<T>(
    List<js.Expression> nodes,
    T Function(List<js.Expression> results) fn,
  ) {
    int oldTempVarIndex = currentTempVarIndex;
    List<js.Expression> visited = [];
    _collectVisited(nodes, visited);
    final result = fn(visited);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  /// Like [withExpressions], but permitting `null` nodes. If any of the nodes
  /// are null, they are ignored, and a null is passed to [fn] in that place.
  T withNullableExpressions<T>(
    List<js.Expression?> nodes,
    T Function(List<js.Expression?> results) fn,
  ) {
    int oldTempVarIndex = currentTempVarIndex;
    List<js.Expression?> visited = [];
    _collectVisited(nodes, visited);
    final result = fn(visited);
    currentTempVarIndex = oldTempVarIndex;
    return result;
  }

  void _collectVisited(
    List<js.Expression?> nodes,
    List<js.Expression?> visited,
  ) {
    // Find last occurrence of a 'transform' expression in [nodes].
    // All expressions before that must be stored in temp-vars.
    int lastTransformIndex = 0;
    for (int i = nodes.length - 1; i >= 0; --i) {
      if (nodes[i] == null) continue;
      if (shouldTransform(nodes[i])) {
        lastTransformIndex = i;
        break;
      }
    }
    for (int i = 0; i < nodes.length; i++) {
      js.Expression? node = nodes[i];
      if (node != null) {
        node = visitExpression(node);
        if (i < lastTransformIndex) {
          node = _storeIfNecessary(node);
        }
      }
      visited.add(node);
    }
  }

  /// Emits the return block that all returns jump to (after going
  /// through all the enclosing finally blocks). The jump to here is made in
  /// [visitReturn].
  void addSuccessExit(js.JavaScriptNodeSourceInformation? sourceInformation);

  /// Emits the block that control flows to if an error has been thrown
  /// but not caught. (after going through all the enclosing finally blocks).
  void addErrorExit(js.JavaScriptNodeSourceInformation? sourceInformation);

  void addFunctionExits(js.JavaScriptNodeSourceInformation? sourceInformation) {
    addSuccessExit(sourceInformation);
    addErrorExit(sourceInformation);
  }

  /// Returns the rewritten function.
  js.Fun finishFunction(
    List<js.Parameter> parameters,
    List<js.Parameter> typeParameters,
    js.Statement rewrittenBody,
    js.VariableDeclarationList variableDeclarations,
    js.JavaScriptNodeSourceInformation? functionSourceInformation,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
  );

  Iterable<js.VariableInitialization> variableInitializations(
    js.JavaScriptNodeSourceInformation? sourceInformation,
  );

  /// Rewrites an async/sync*/async* function to a normal JavaScript function.
  ///
  /// The control flow is flattened by simulating 'goto' using a switch in a
  /// loop and a state variable [goto] inside a nested function [body]
  /// that can be called back by [asyncStarHelper]/[asyncStarHelper]/the
  /// [Iterator].
  ///
  /// Local variables are hoisted outside the helper.
  ///
  /// Awaits in async/async* are translated to code that remembers the current
  /// location (so the function can resume from where it was) followed by a
  /// [awaitStatement]. The helper sets up the waiting for the awaited
  /// value and returns a future which is immediately returned by the
  /// [awaitStatement].
  ///
  /// Yields in sync*/async* are translated to a calls to helper functions.
  /// (see [visitYield])
  ///
  /// Simplified examples (not the exact translation, but intended to show the
  /// ideas):
  ///
  /// function (x, y, z) async {
  ///   var p = await foo();
  ///   return bar(p);
  /// }
  ///
  /// Becomes (without error handling):
  ///
  /// function(x, y, z) {
  ///   var goto = 0, returnValue, completer = new Completer(), p;
  ///   function body(result) {
  ///     while (true) {
  ///       switch (goto) {
  ///         case 0:
  ///           goto = 1 // Remember where to continue when the future succeeds.
  ///           return thenHelper(foo(), helper, completer);
  ///         case 1:
  ///           p = result;
  ///           returnValue = bar(p);
  ///           goto = 2;
  ///           break;
  ///         case 2:
  ///           return thenHelper(returnValue, null, completer)
  ///       }
  ///     }
  ///     return thenHelper(null, helper, completer);
  ///   }
  /// }
  ///
  /// Try/catch is implemented by maintaining [handler] to contain the label
  /// of the current handler. If [body] throws, the caller should catch the
  /// error and recall [body] with first argument [status_codes.ERROR] and
  /// second argument the error.
  ///
  /// A `finally` clause is compiled similar to normal code, with the additional
  /// complexity that `finally` clauses need to know where to jump to after the
  /// clause is done. In the translation, each flow-path that enters a `finally`
  /// sets up the variable [next] with a stack of finally-blocks and a final
  /// jump-target (exit, catch, ...).
  ///
  /// function(x, y, z) async {
  ///   try {
  ///     try {
  ///       throw "error";
  ///     } finally {
  ///       finalize1();
  ///     }
  ///   } catch (e) {
  ///     handle(e);
  ///   } finally {
  ///     finalize2();
  ///   }
  /// }
  ///
  /// Translates into (besides the fact that structures not containing
  /// await/yield/yield* are left intact):
  ///
  /// function(x, y, z) {
  ///   var goto = 0;
  ///   var returnValue;
  ///   var completer = new Completer();
  ///   var handler = 8; // Outside try-blocks go to the rethrow label.
  ///   var p;
  ///   var currentError;
  ///   // The result can be either the result of an awaited future, or an
  ///   // error if the future completed with an error.
  ///   function body(errorCode, result) {
  ///     if (errorCode == 1) {
  ///       currentError = result;
  ///       goto = handler;
  ///     }
  ///     while (true) {
  ///       switch (goto) {
  ///         case 0:
  ///           handler = 4; // The outer catch-handler
  ///           handler = 1; // The inner (implicit) catch-handler
  ///           throw "error";
  ///           next = [3];
  ///           // After the finally (2) continue normally after the try.
  ///           goto = 2;
  ///           break;
  ///         case 1: // (implicit) catch handler for inner try.
  ///           next = [3]; // destination after the finally.
  ///           // fall-though to the finally handler.
  ///         case 2: // finally for inner try
  ///           handler = 4; // catch-handler for outer try.
  ///           finalize1();
  ///           goto = next.pop();
  ///           break;
  ///         case 3: // exiting inner try.
  ///           next = [6];
  ///           goto = 5; // finally handler for outer try.
  ///           break;
  ///         case 4: // catch handler for outer try.
  ///           handler = 5; // If the handler throws, do the finally ..
  ///           next = [8] // ... and rethrow.
  ///           e = storedError;
  ///           handle(e);
  ///           // Fall through to finally.
  ///         case 5: // finally handler for outer try.
  ///           handler = null;
  ///           finalize2();
  ///           goto = next.pop();
  ///           break;
  ///         case 6: // Exiting outer try.
  ///         case 7: // return
  ///           return thenHelper(returnValue, 0, completer);
  ///         case 8: // Rethrow
  ///           return thenHelper(currentError, 1, completer);
  ///       }
  ///     }
  ///     return thenHelper(null, helper, completer);
  ///   }
  /// }
  ///
  /// [bodySourceInformation] is used on code generated to execute the function
  /// body and [exitSourceInformation] is used on code generated to exit the
  /// function.
  js.Fun rewriteFunction(
    js.Fun node,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
    js.JavaScriptNodeSourceInformation? exitSourceInformation,
  ) {
    beginLabel(newLabel("Function start"));
    // AsyncStar needs a return label for its handling of cancellation. See
    // [visitDartYield].
    exitLabel =
        (analysis.hasExplicitReturns || isAsyncStar)
            ? newLabel("return")
            : null;
    handlerLabels[node] = rethrowLabel = newLabel("rethrow");
    js.Statement body = node.body;
    jumpTargets.add(node);
    visitStatement(body);
    jumpTargets.removeLast();
    addFunctionExits(exitSourceInformation);

    List<js.SwitchClause> clauses = [
      for (final entry in labelledParts.entries)
        js.Case(js.number(entry.key), js.Block(entry.value)),
    ];
    js.Statement rewrittenBody = js.Switch(
      goto,
      clauses,
    ).withSourceInformation(bodySourceInformation);
    if (hasJumpThoughOuterLabel) {
      rewrittenBody = js.LabeledStatement(outerLabelName, rewrittenBody);
    }
    rewrittenBody = js.js
        .statement('while (true) #', rewrittenBody)
        .withSourceInformation(bodySourceInformation);
    List<js.VariableInitialization> variables = [];

    variables.add(
      _makeVariableInitializer(goto, js.number(0), bodySourceInformation),
    );
    variables.addAll(variableInitializations(bodySourceInformation));
    if (hasHandlerLabels) {
      variables.add(
        _makeVariableInitializer(
          handler,
          js.number(rethrowLabel),
          bodySourceInformation,
        ),
      );
      variables.add(
        _makeVariableInitializer(
          errorStack,
          js.ArrayInitializer(const []),
          bodySourceInformation,
        ),
      );
    }
    if (analysis.hasFinally || (isAsyncStar && analysis.hasYield)) {
      variables.add(
        _makeVariableInitializer(
          next,
          js.ArrayInitializer([]),
          bodySourceInformation,
        ),
      );
    }
    if (analysis.hasThis && !isSyncStar) {
      // Sync* functions must remember `this` on the level of the outer
      // function.
      variables.add(
        _makeVariableInitializer(self, js.js('this'), bodySourceInformation),
      );
    }
    variables.addAll(
      localVariables.map((js.VariableDeclaration declaration) {
        return js.VariableInitialization(declaration, null);
      }),
    );
    variables.addAll(
      Iterable.generate(
        tempVarHighWaterMark,
        (int i) => _makeVariableInitializer(
          useTempVar(i + 1).name,
          null,
          bodySourceInformation,
        ),
      ),
    );
    js.VariableDeclarationList variableDeclarations =
        js.VariableDeclarationList(variables);

    // Names are already safe when added.
    List<js.Parameter> typeParameters =
        typeArgumentNames.map((name) => js.Parameter(name)).toList();
    return finishFunction(
      node.params,
      typeParameters,
      rewrittenBody,
      variableDeclarations,
      node.sourceInformation,
      bodySourceInformation,
    );
  }

  js.Expression visitFunctionExpression(js.FunctionExpression node) {
    if (node.asyncModifier.isAsync || node.asyncModifier.isYielding) {
      // The translation does not handle nested functions that are generators
      // or asynchronous.  These functions should only be ones that are
      // introduced by JS foreign code from our own libraries.
      reporter.internalError(
        spannable,
        'Nested function is a generator or asynchronous.',
      );
    }
    return node;
  }

  @override
  js.Expression visitFun(js.Fun node) {
    return visitFunctionExpression(node);
  }

  @override
  js.Expression visitArrowFunction(js.ArrowFunction node) {
    return visitFunctionExpression(node);
  }

  @override
  js.Expression visitAccess(js.PropertyAccess node) {
    return withExpression2(
      node.receiver,
      node.selector,
      (receiver, selector) =>
          js.PropertyAccess(receiver, selector).withInformationFrom(node),
    );
  }

  @override
  js.Expression visitArrayHole(js.ArrayHole node) {
    return node;
  }

  @override
  js.Expression visitArrayInitializer(js.ArrayInitializer node) {
    return withExpressions(node.elements, (elements) {
      return js.ArrayInitializer(elements);
    });
  }

  @override
  js.Expression visitAssignment(js.Assignment node) {
    if (!shouldTransform(node)) {
      return js.Assignment.compound(
        visitExpression(node.leftHandSide),
        node.op,
        visitExpression(node.value),
      );
    }
    js.Expression leftHandSide = node.leftHandSide;
    if (leftHandSide is js.VariableUse) {
      return withExpression(node.value, (js.Expression value) {
        // A non-compound [js.Assignment] has `op==null`. So it works out to
        // use [js.Assignment.compound] for all cases.
        // Visit the [js.VariableUse] to ensure renaming is done correctly.
        return js.Assignment.compound(
          visitExpression(leftHandSide),
          node.op,
          value,
        );
      }, store: false);
    } else if (leftHandSide is js.PropertyAccess) {
      return withExpressions(
        [leftHandSide.receiver, leftHandSide.selector, node.value],
        (evaluated) {
          return js.Assignment.compound(
            js.PropertyAccess(evaluated[0], evaluated[1]),
            node.op,
            evaluated[2],
          );
        },
      );
    } else {
      throw "Unexpected assignment left hand side $leftHandSide";
    }
  }

  js.Statement awaitStatement(
    js.Expression value,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  );

  /// An await is translated to an [awaitStatement].
  ///
  /// See the comments of [rewriteFunction] for an example.
  @override
  js.Expression visitAwait(js.Await node) {
    assert(isAsync || isAsyncStar);
    int afterAwait = newLabel("returning from await.");
    withExpression(node.expression, (js.Expression value) {
      addStatement(setGotoVariable(afterAwait, node.sourceInformation));
      addStatement(awaitStatement(value, node.sourceInformation));
    }, store: false);
    beginLabel(afterAwait);
    return result;
  }

  /// Checks if [node] is the variable named [resultName].
  ///
  /// [result] is used to hold the result of a transformed computation
  /// for example the result of awaiting, or the result of a conditional or
  /// short-circuiting expression.
  /// If the subexpression of some transformed node already is transformed and
  /// visiting it returns [result], it is not redundantly assigned to itself
  /// again.
  bool isResult(js.Expression node) {
    return node is js.VariableUse && node.name == resultName;
  }

  @override
  js.Expression visitBinary(js.Binary node) {
    if (shouldTransform(node.right) && (node.op == "||" || node.op == "&&")) {
      int thenLabel = newLabel("then");
      int joinLabel = newLabel("join");
      withExpression(node.left, (js.Expression left) {
        js.Statement assignLeft =
            isResult(left)
                ? js.Block.empty()
                : js.js.statement('# = #;', [result, left]);
        if (node.op == "&&") {
          addStatement(
            js.js.statement('if (#) #; else #', [
              left,
              gotoAndBreak(thenLabel, node.sourceInformation),
              assignLeft,
            ]),
          );
        } else {
          assert(node.op == "||");
          addStatement(
            js.js.statement('if (#) #; else #', [
              left,
              assignLeft,
              gotoAndBreak(thenLabel, node.sourceInformation),
            ]),
          );
        }
      }, store: true);
      addGoto(joinLabel, node.sourceInformation);
      beginLabel(thenLabel);
      withExpression(node.right, (js.Expression value) {
        if (!isResult(value)) {
          addStatement(js.js.statement('# = #;', [result, value]));
        }
      }, store: false);
      beginLabel(joinLabel);
      return result;
    }

    return withExpression2(
      node.left,
      node.right,
      (left, right) => js.Binary(node.op, left, right),
    );
  }

  @override
  void visitBlock(js.Block node) {
    for (js.Statement statement in node.statements) {
      visitStatement(statement);
    }
  }

  @override
  void visitBreak(js.Break node) {
    js.Node target = analysis.targets[node]!;
    if (!shouldTransform(target)) {
      addStatement(node);
      return;
    }
    translateJump(target, breakLabels[target], node.sourceInformation);
  }

  @override
  js.Expression visitCall(js.Call node) {
    bool storeTarget = node.arguments.any(shouldTransform);
    return withCallTargetExpression(node.target, (target) {
      return withExpressions(node.arguments, (List<js.Expression> arguments) {
        return js.Call(target, arguments).withInformationFrom(node);
      });
    }, store: storeTarget);
  }

  @override
  void visitCase(js.Case node) {
    unreachable(node);
  }

  @override
  void visitCatch(js.Catch node) {
    unreachable(node);
  }

  @override
  void visitComment(js.Comment node) {
    addStatement(node);
  }

  @override
  js.Expression visitConditional(js.Conditional node) {
    if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
      return js
          .js('# ? # : #', [
            visitExpression(node.condition),
            visitExpression(node.then),
            visitExpression(node.otherwise),
          ])
          .withSourceInformation(node.sourceInformation);
    }
    int thenLabel = newLabel("then");
    int joinLabel = newLabel("join");
    int elseLabel = newLabel("else");
    withExpression(node.condition, (js.Expression condition) {
      addStatement(
        js.js.statement('# = # ? # : #;', [
          goto,
          condition,
          js.number(thenLabel),
          js.number(elseLabel),
        ]),
      );
    }, store: false);
    addBreak(node.sourceInformation);
    beginLabel(thenLabel);
    withExpression(node.then, (js.Expression value) {
      if (!isResult(value)) {
        addStatement(js.js.statement('# = #;', [result, value]));
      }
    }, store: false);
    addGoto(joinLabel, node.sourceInformation);
    beginLabel(elseLabel);
    withExpression(node.otherwise, (js.Expression value) {
      if (!isResult(value)) {
        addStatement(js.js.statement('# = #;', [result, value]));
      }
    }, store: false);
    beginLabel(joinLabel);
    return result;
  }

  @override
  void visitContinue(js.Continue node) {
    js.Node? target = analysis.targets[node];
    if (!shouldTransform(target)) {
      addStatement(node);
      return;
    }
    translateJump(target, continueLabels[target!], node.sourceInformation);
  }

  /// Emits a break statement that exits the big switch statement.
  void addBreak(js.JavaScriptNodeSourceInformation? sourceInformation) {
    if (insideUntranslatedBreakable) {
      hasJumpThoughOuterLabel = true;
      addStatement(
        js.Break(outerLabelName).withSourceInformation(sourceInformation),
      );
    } else {
      addStatement(js.Break(null).withSourceInformation(sourceInformation));
    }
  }

  /// Common code for handling break, continue, return.
  ///
  /// It is necessary to run all nesting finally-handlers between the jump and
  /// the target. For that [next] is used as a stack of places to go.
  ///
  /// See also [rewriteFunction].
  void translateJump(
    js.Node? target,
    int? targetLabel,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    // Compute a stack of all the 'finally' nodes that must be visited before
    // the jump.
    // The bottom of the stack is the label where the jump goes to.
    List<int> jumpStack = [];
    for (js.Node node in jumpTargets.reversed) {
      if (finallyLabels[node] != null) {
        jumpStack.add(finallyLabels[node]!);
      } else if (node == target) {
        jumpStack.add(targetLabel!);
        break;
      }
      // Ignore other nodes.
    }
    jumpStack = jumpStack.reversed.toList();
    // As the program jumps directly to the top of the stack, it is taken off
    // now.
    int firstTarget = jumpStack.removeLast();
    if (jumpStack.isNotEmpty) {
      js.Expression jsJumpStack = js.ArrayInitializer(
        jumpStack.map((int label) => js.number(label)).toList(),
      );
      addStatement(
        js.ExpressionStatement(
          js
              .js("# = #", [next, jsJumpStack])
              .withSourceInformation(sourceInformation),
        ),
      );
    }
    addGoto(firstTarget, sourceInformation);
  }

  @override
  void visitDefault(js.Default node) => unreachable(node);

  @override
  void visitDo(js.Do node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslatedBreakable = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      addStatement(
        js.js.statement('do {#} while (#)', [
          translateToStatement(node.body),
          visitExpression(node.condition),
        ]),
      );
      insideUntranslatedBreakable = oldInsideUntranslatedBreakable;
      return;
    }
    int startLabel = newLabel("do body");

    int continueLabel = newLabel("do condition");
    continueLabels[node] = continueLabel;

    int afterLabel = newLabel("after do");
    breakLabels[node] = afterLabel;

    beginLabel(startLabel);

    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();

    beginLabel(continueLabel);
    withExpression(node.condition, (js.Expression condition) {
      addStatement(
        js.js.statement('if (#) #', [
          condition,
          gotoAndBreak(startLabel, node.sourceInformation),
        ]),
      );
    }, store: false);
    beginLabel(afterLabel);
  }

  @override
  void visitEmptyStatement(js.EmptyStatement node) {
    addStatement(node);
  }

  @override
  void visitExpressionStatement(js.ExpressionStatement node) {
    visitExpressionIgnoreResult(node.expression);
  }

  @override
  void visitFor(js.For node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      // Note that node.init, node.condition, node.update all can be null, but
      // withNullableExpressions handles that.
      withNullableExpressions([node.init, node.condition, node.update], (
        List<js.Expression?> transformed,
      ) {
        addStatement(
          js.For(
            transformed[0],
            transformed[1],
            transformed[2],
            translateToStatement(node.body),
          ),
        );
      });
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }

    if (node.init != null) {
      visitExpressionIgnoreResult(node.init!);
    }
    int startLabel = newLabel("for condition");
    // If there is no update, continuing the loop is the same as going to the
    // start.
    int continueLabel =
        (node.update == null) ? startLabel : newLabel("for update");
    continueLabels[node] = continueLabel;
    int afterLabel = newLabel("after for");
    breakLabels[node] = afterLabel;
    beginLabel(startLabel);
    js.Expression? condition = node.condition;
    if (condition == null ||
        (condition is js.LiteralBool && condition.value == true)) {
      addStatement(js.Comment("trivial condition"));
    } else {
      withExpression(condition, (js.Expression condition) {
        addStatement(
          js.If.noElse(
            js.Prefix("!", condition),
            gotoAndBreak(afterLabel, node.sourceInformation),
          ),
        );
      }, store: false);
    }
    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    if (node.update != null) {
      beginLabel(continueLabel);
      visitExpressionIgnoreResult(node.update!);
    }
    addGoto(startLabel, node.sourceInformation);
    beginLabel(afterLabel);
  }

  @override
  void visitForIn(js.ForIn node) {
    // The dart output currently never uses for-in loops.
    throw "JavaScript for-in not implemented yet in the await transformation";
  }

  @override
  void visitFunctionDeclaration(js.FunctionDeclaration node) {
    unsupported(node);
  }

  List<js.Statement> translateToStatementSequence(js.Statement node) {
    assert(!shouldTransform(node));
    List<js.Statement> oldBuffer = currentStatementBuffer;
    currentStatementBuffer = [];
    List<js.Statement> resultBuffer = currentStatementBuffer;
    visitStatement(node);
    currentStatementBuffer = oldBuffer;
    return resultBuffer;
  }

  js.Statement translateToStatement(js.Statement node) {
    List<js.Statement> statements = translateToStatementSequence(node);
    if (statements.length == 1) return statements.single;
    return js.Block(statements);
  }

  js.Block translateToBlock(js.Statement node) {
    return js.Block(translateToStatementSequence(node));
  }

  @override
  void visitIf(js.If node) {
    if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
      withExpression(node.condition, (js.Expression condition) {
        js.Statement translatedThen = translateToStatement(node.then);
        js.Statement translatedElse = translateToStatement(node.otherwise);
        addStatement(js.If(condition, translatedThen, translatedElse));
      }, store: false);
      return;
    }
    int thenLabel = newLabel("then");
    int joinLabel = newLabel("join");
    int elseLabel =
        (node.otherwise is js.EmptyStatement) ? joinLabel : newLabel("else");

    withExpression(node.condition, (js.Expression condition) {
      addExpressionStatement(
        js.Assignment(
          goto,
          js.Conditional(condition, js.number(thenLabel), js.number(elseLabel)),
        ),
      );
    }, store: false);
    addBreak(node.sourceInformation);
    beginLabel(thenLabel);
    visitStatement(node.then);
    if (node.otherwise is! js.EmptyStatement) {
      addGoto(joinLabel, node.sourceInformation);
      beginLabel(elseLabel);
      visitStatement(node.otherwise);
    }
    beginLabel(joinLabel);
  }

  @override
  Never visitInterpolatedExpression(js.InterpolatedExpression node) {
    unsupported(node);
  }

  @override
  Never visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
    unsupported(node);
  }

  @override
  Never visitInterpolatedLiteral(js.InterpolatedLiteral node) {
    unsupported(node);
  }

  @override
  Never visitInterpolatedParameter(js.InterpolatedParameter node) {
    unsupported(node);
  }

  @override
  Never visitInterpolatedSelector(js.InterpolatedSelector node) {
    unsupported(node);
  }

  @override
  Never visitInterpolatedStatement(js.InterpolatedStatement node) {
    unsupported(node);
  }

  @override
  void visitLabeledStatement(js.LabeledStatement node) {
    if (!shouldTransform(node)) {
      addStatement(
        js.LabeledStatement(node.label, translateToStatement(node.body)),
      );
      return;
    }
    // `continue label` is really continuing the nested loop.
    // This is set up in [PreTranslationAnalysis.visitContinue].
    // Here we only need a breakLabel:
    int breakLabel = newLabel("break ${node.label}");
    breakLabels[node] = breakLabel;

    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    beginLabel(breakLabel);
  }

  @override
  js.Expression visitLiteralBool(js.LiteralBool node) => node;

  @override
  Never visitLiteralExpression(js.LiteralExpression node) => unsupported(node);

  @override
  js.Expression visitLiteralNull(js.LiteralNull node) => node;

  @override
  js.Expression visitLiteralNumber(js.LiteralNumber node) => node;

  @override
  Never visitLiteralStatement(js.LiteralStatement node) => unsupported(node);

  @override
  js.Expression visitLiteralString(js.LiteralString node) => node;

  @override
  js.Expression visitStringConcatenation(js.StringConcatenation node) => node;

  @override
  js.Name visitName(js.Name node) => node;

  @override
  js.Parentheses visitParentheses(js.Parentheses node) {
    unsupported(node);
  }

  @override
  Never visitNamedFunction(js.NamedFunction node) {
    unsupported(node);
  }

  @override
  js.Expression visitDeferredExpression(js.DeferredExpression node) => node;

  @override
  Never visitDeferredStatement(js.DeferredStatement node) => unsupported(node);

  @override
  js.Expression visitDeferredNumber(js.DeferredNumber node) => node;

  @override
  js.Expression visitDeferredString(js.DeferredString node) => node;

  @override
  js.Expression visitNew(js.New node) {
    bool storeTarget = node.arguments.any(shouldTransform);
    return withCallTargetExpression(node.target, (target) {
      return withExpressions(node.arguments, (List<js.Expression> arguments) {
        return js.New(target, arguments);
      });
    }, store: storeTarget);
  }

  @override
  js.Expression visitObjectInitializer(js.ObjectInitializer node) {
    return withExpressions(
      node.properties.map((js.Property property) => property.value).toList(),
      (List<js.Expression> values) {
        List<js.Property> properties = List.generate(values.length, (int i) {
          if (node.properties[i] is js.MethodDefinition) {
            return js.MethodDefinition(
              node.properties[i].name,
              values[i] as js.Fun,
            );
          }
          return js.Property(node.properties[i].name, values[i]);
        });
        return js.ObjectInitializer(properties);
      },
    );
  }

  @override
  Never visitParameter(js.Parameter node) => unreachable(node);

  @override
  js.Expression visitPostfix(js.Postfix node) {
    if (node.op == "++" || node.op == "--") {
      js.Expression argument = node.argument;
      if (argument is js.VariableUse) {
        return js.Postfix(node.op, visitExpression(argument));
      } else if (argument is js.PropertyAccess) {
        return withExpression2(argument.receiver, argument.selector, (
          receiver,
          selector,
        ) {
          return js.Postfix(node.op, js.PropertyAccess(receiver, selector));
        });
      } else {
        throw "Unexpected postfix ${node.op} "
            "operator argument ${node.argument}";
      }
    }
    return withExpression(
      node.argument,
      (js.Expression argument) => js.Postfix(node.op, argument),
      store: false,
    );
  }

  @override
  js.Expression visitPrefix(js.Prefix node) {
    if (node.op == "++" || node.op == "--") {
      js.Expression argument = node.argument;
      if (argument is js.VariableUse) {
        return js.Prefix(node.op, visitExpression(argument));
      } else if (argument is js.PropertyAccess) {
        return withExpression2(argument.receiver, argument.selector, (
          receiver,
          selector,
        ) {
          return js.Prefix(node.op, js.PropertyAccess(receiver, selector));
        });
      } else {
        throw "Unexpected prefix ${node.op} operator "
            "argument ${node.argument}";
      }
    }
    return withExpression(
      node.argument,
      (js.Expression argument) => js.Prefix(node.op, argument),
      store: false,
    );
  }

  @override
  Never visitProgram(js.Program node) => unsupported(node);

  @override
  js.Property visitProperty(js.Property node) {
    assert(node.runtimeType == js.Property);
    return withExpression(
      node.value,
      (js.Expression value) => js.Property(node.name, value),
      store: false,
    );
  }

  @override
  js.MethodDefinition visitMethodDefinition(js.MethodDefinition node) {
    return withExpression(
      node.function,
      (js.Expression value) => js.MethodDefinition(node.name, value as js.Fun),
      store: false,
    );
  }

  @override
  js.Expression visitRegExpLiteral(js.RegExpLiteral node) => node;

  @override
  void visitReturn(js.Return node) {
    js.Node? target = analysis.targets[node];
    final expression = node.value;
    if (expression != null) {
      if (isSyncStar || isAsyncStar) {
        // Even though `return expr;` is not allowed in the dart sync* and
        // async*  code, the backend sometimes generates code like this, but
        // only when it is known that the 'expr' throws, and the return is just
        // to tell the JavaScript VM that the code won't continue here.
        // It is therefore interpreted as `expr; return;`
        visitExpressionIgnoreResult(expression);
      } else {
        withExpression(expression, (js.Expression value) {
          addStatement(
            js.js
                .statement("# = #;", [returnValue, value])
                .withSourceInformation(node.sourceInformation),
          );
        }, store: false);
      }
    }
    translateJump(target, exitLabel, node.sourceInformation);
  }

  @override
  void visitSwitch(js.Switch node) {
    if (!shouldTransform(node)) {
      // TODO(sra): If only the key has an await, translation can be simplified.
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      withExpression(node.key, (js.Expression key) {
        List<js.SwitchClause> cases =
            node.cases.map((js.SwitchClause clause) {
              if (clause is js.Case) {
                return js.Case(
                  clause.expression,
                  translateToBlock(clause.body),
                );
              } else {
                return js.Default(
                  translateToBlock((clause as js.Default).body),
                );
              }
            }).toList();
        addStatement(js.Switch(key, cases));
      }, store: false);
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }
    int before = newLabel("switch");
    int after = newLabel("after switch");
    breakLabels[node] = after;

    beginLabel(before);
    List<int> labels = List<int>.filled(node.cases.length, -1);

    bool anyCaseExpressionTransformed = node.cases.any(
      (js.SwitchClause x) => x is js.Case && shouldTransform(x.expression),
    );
    if (anyCaseExpressionTransformed) {
      int? defaultIndex; // Null means no default was found.
      // If there is an await in one of the keys, a chain of ifs has to be used.

      withExpression(node.key, (js.Expression key) {
        int i = 0;
        for (js.SwitchClause clause in node.cases) {
          if (clause is js.Default) {
            // The goto for the default case is added after all non-default
            // clauses have been handled.
            defaultIndex = i;
            labels[i] = newLabel("default");
            continue;
          } else if (clause is js.Case) {
            labels[i] = newLabel("case");
            withExpression(clause.expression, (expression) {
              addStatement(
                js.If.noElse(
                  js.Binary("===", key, expression),
                  gotoAndBreak(labels[i], clause.sourceInformation),
                ),
              );
            }, store: false);
          }
          i++;
        }
      }, store: true);

      if (defaultIndex == null) {
        addGoto(after, node.sourceInformation);
      } else {
        addGoto(labels[defaultIndex!], node.sourceInformation);
      }
    } else {
      bool hasDefault = false;
      int i = 0;
      List<js.SwitchClause> clauses = [];
      for (js.SwitchClause clause in node.cases) {
        if (clause is js.Case) {
          labels[i] = newLabel("case");
          clauses.add(
            js.Case(
              visitExpression(clause.expression),
              gotoAndBreak(labels[i], clause.sourceInformation),
            ),
          );
        } else if (clause is js.Default) {
          labels[i] = newLabel("default");
          clauses.add(
            js.Default(gotoAndBreak(labels[i], clause.sourceInformation)),
          );
          hasDefault = true;
        } else {
          reporter.internalError(spannable, "Unknown clause type $clause");
        }
        i++;
      }
      if (!hasDefault) {
        clauses.add(js.Default(gotoAndBreak(after, node.sourceInformation)));
      }
      withExpression(node.key, (js.Expression key) {
        addStatement(js.Switch(key, clauses));
      }, store: false);

      addBreak(node.sourceInformation);
    }

    jumpTargets.add(node);
    for (int i = 0; i < labels.length; i++) {
      beginLabel(labels[i]);
      visitStatement(node.cases[i].body);
    }
    beginLabel(after);
    jumpTargets.removeLast();
  }

  @override
  js.Expression visitThis(js.This node) {
    return self;
  }

  @override
  void visitThrow(js.Throw node) {
    withExpression(node.expression, (js.Expression expression) {
      addStatement(
        js.Throw(expression).withSourceInformation(node.sourceInformation),
      );
    }, store: false);
  }

  void setErrorHandler([int? errorHandler]) {
    hasHandlerLabels = true; // TODO(sra): Add short form error handler.
    js.Expression label =
        (errorHandler == null) ? currentErrorHandler : js.number(errorHandler);
    addStatement(js.js.statement('# = #;', [handler, label]));
  }

  List<int> _finalliesUpToAndEnclosingHandler() {
    List<int> result = [];
    for (int i = jumpTargets.length - 1; i >= 0; i--) {
      js.Node node = jumpTargets[i];
      int? handlerLabel = handlerLabels[node];
      if (handlerLabel != null) {
        result.add(handlerLabel);
        break;
      }
      int? finallyLabel = finallyLabels[node];
      if (finallyLabel != null) {
        result.add(finallyLabel);
      }
    }
    return result.reversed.toList();
  }

  /// See the comments of [rewriteFunction] for more explanation.
  @override
  void visitTry(js.Try node) {
    final catchPart = node.catchPart;
    final finallyPart = node.finallyPart;

    if (!shouldTransform(node)) {
      js.Block body = translateToBlock(node.body);
      js.Catch? translatedCatchPart;
      if (catchPart != null) {
        // JavaScript catch variable bindings are a local scope of the catch
        // block so shadow any catch variable bindings that might collide with
        // this one so that references to this binding do not get renamed.
        variableRenamings.add((
          catchPart.declaration.name,
          catchPart.declaration.name,
        ));
        translatedCatchPart = js.Catch(
          catchPart.declaration,
          translateToBlock(catchPart.body),
        );
        variableRenamings.removeLast();
      }
      js.Block? translatedFinallyPart =
          (finallyPart == null) ? null : translateToBlock(finallyPart);
      addStatement(js.Try(body, translatedCatchPart, translatedFinallyPart));
      return;
    }

    hasTryBlocks = true;
    int uncaughtLabel = newLabel("uncaught");
    int handlerLabel = (catchPart == null) ? uncaughtLabel : newLabel("catch");

    int finallyLabel = newLabel("finally");
    int afterFinallyLabel = newLabel("after finally");
    if (finallyPart != null) {
      finallyLabels[finallyPart] = finallyLabel;
      jumpTargets.add(finallyPart);
    }

    handlerLabels[node] = handlerLabel;
    jumpTargets.add(node);

    // Set the error handler here. It must be cleared on every path out;
    // normal and error exit.
    setErrorHandler();

    visitStatement(node.body);

    js.Node last = jumpTargets.removeLast();
    assert(last == node);

    if (finallyPart == null) {
      setErrorHandler();
      addGoto(afterFinallyLabel, node.sourceInformation);
    } else {
      // The handler is reset as the first thing in the finally block.
      addStatement(
        js.js.statement("#.push(#);", [next, js.number(afterFinallyLabel)]),
      );
      addGoto(finallyLabel, node.sourceInformation);
    }

    if (catchPart != null) {
      beginLabel(handlerLabel);
      // [uncaughtLabel] is the handler for the code in the catch-part.
      // It ensures that [nextName] is set up to run the right finally blocks.
      handlerLabels[catchPart] = uncaughtLabel;
      jumpTargets.add(catchPart);
      setErrorHandler();
      // The catch declaration name can shadow outer variables, so a fresh name
      // is needed to avoid collisions.  See Ecma 262, 3rd edition,
      // section 12.14.
      String errorRename = freshName(catchPart.declaration.name);
      localVariables.add(js.VariableDeclaration(errorRename));
      variableRenamings.add((catchPart.declaration.name, errorRename));
      addStatement(js.js.statement("# = #.pop();", [errorRename, errorStack]));
      visitStatement(catchPart.body);
      variableRenamings.removeLast();
      if (finallyPart != null) {
        // The error has been caught, so after the finally, continue after the
        // try.
        addStatement(
          js.js.statement("#.push(#);", [next, js.number(afterFinallyLabel)]),
        );
        addGoto(finallyLabel, node.sourceInformation);
      } else {
        addGoto(afterFinallyLabel, node.sourceInformation);
      }
      js.Node last = jumpTargets.removeLast();
      assert(last == catchPart);
    }

    // The "uncaught"-handler tells the finally-block to continue with
    // the enclosing finally-blocks until the current catch-handler.
    beginLabel(uncaughtLabel);

    List<int> enclosingFinallies = _finalliesUpToAndEnclosingHandler();

    int nextLabel = enclosingFinallies.removeLast();
    if (enclosingFinallies.isNotEmpty) {
      // [enclosingFinallies] can be empty if there is no surrounding finally
      // blocks. Then [nextLabel] will be [rethrowLabel].
      addStatement(
        js.js.statement("# = #;", [
          next,
          js.ArrayInitializer(enclosingFinallies.map(js.number).toList()),
        ]),
      );
    }
    if (finallyPart == null) {
      // The finally-block belonging to [node] will be visited because of
      // fallthrough. If it does not exist, add an explicit goto.
      addGoto(nextLabel, node.sourceInformation);
    }
    if (finallyPart != null) {
      js.Node last = jumpTargets.removeLast();
      assert(last == finallyPart);

      beginLabel(finallyLabel);
      setErrorHandler();
      visitStatement(finallyPart);
      addStatement(js.Comment("// goto the next finally handler"));
      addStatement(js.js.statement("# = #.pop();", [goto, next]));
      addBreak(node.sourceInformation);
    }
    beginLabel(afterFinallyLabel);
  }

  @override
  Never visitVariableDeclaration(js.VariableDeclaration node) {
    unreachable(node);
  }

  @override
  js.Expression visitVariableDeclarationList(js.VariableDeclarationList node) {
    for (js.VariableInitialization initialization in node.declarations) {
      js.VariableDeclaration declaration =
          initialization.declaration as js.VariableDeclaration;
      localVariables.add(declaration);
      if (initialization.value != null) {
        withExpression(initialization.value!, (js.Expression value) {
          addExpressionStatement(
            js.Assignment(js.VariableUse(declaration.name), value),
          );
        }, store: false);
      }
    }
    return js.number(0); // Dummy expression.
  }

  @override
  void visitVariableInitialization(js.VariableInitialization node) {
    unreachable(node);
  }

  @override
  js.Expression visitVariableUse(js.VariableUse node) {
    for (final renaming in variableRenamings.reversed) {
      if (renaming.$1 == node.name) return js.VariableUse(renaming.$2);
    }
    return node;
  }

  @override
  void visitWhile(js.While node) {
    if (!shouldTransform(node)) {
      bool oldInsideUntranslated = insideUntranslatedBreakable;
      insideUntranslatedBreakable = true;
      withExpression(node.condition, (js.Expression condition) {
        addStatement(js.While(condition, translateToStatement(node.body)));
      }, store: false);
      insideUntranslatedBreakable = oldInsideUntranslated;
      return;
    }
    int continueLabel = newLabel("while condition");
    continueLabels[node] = continueLabel;
    beginLabel(continueLabel);

    int afterLabel = newLabel("after while");
    breakLabels[node] = afterLabel;
    js.Expression condition = node.condition;
    // If the condition is `true`, a test is not needed.
    if (!(condition is js.LiteralBool && condition.value == true)) {
      withExpression(node.condition, (js.Expression condition) {
        addStatement(
          js.If.noElse(
            js.Prefix("!", condition),
            gotoAndBreak(afterLabel, node.sourceInformation),
          ),
        );
      }, store: false);
    }
    jumpTargets.add(node);
    visitStatement(node.body);
    jumpTargets.removeLast();
    addGoto(continueLabel, node.sourceInformation);
    beginLabel(afterLabel);
  }

  void addYield(
    js.DartYield node,
    js.Expression expression,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  );

  @override
  void visitDartYield(js.DartYield node) {
    assert(isSyncStar || isAsyncStar);
    int label = newLabel("after yield");
    // Don't do a break here for the goto, but instead a return in either
    // addSynYield or addAsyncYield.
    withExpression(node.expression, (js.Expression expression) {
      addStatement(setGotoVariable(label, node.sourceInformation));
      addYield(node, expression, node.sourceInformation);
    }, store: false);
    beginLabel(label);
  }
}

js.VariableInitialization _makeVariableInitializer(
  dynamic variable,
  js.Expression? initValue,
  js.JavaScriptNodeSourceInformation? sourceInformation,
) {
  js.VariableDeclaration declaration;
  if (variable is js.VariableUse) {
    declaration = js.VariableDeclaration(variable.name);
  } else if (variable is String) {
    declaration = js.VariableDeclaration(variable);
  } else {
    assert(variable is js.VariableDeclaration);
    declaration = variable;
  }
  return js.VariableInitialization(
        declaration,
        initValue,
      ).withSourceInformation(sourceInformation)
      as js.VariableInitialization;
}

class AsyncRewriter extends AsyncRewriterBase {
  @override
  bool get isAsync => true;

  /// The Completer that will finish an async function.
  ///
  /// Not used for sync* or async* functions.
  late final String completerName;
  js.VariableUse get completer => js.VariableUse(completerName);

  /// The function called by an async function to initiate asynchronous
  /// execution of the body.  This is called with:
  ///
  /// - The body function [bodyName].
  /// - the completer object [completer].
  ///
  /// It returns the completer's future. Passing the completer and returning its
  /// future is a convenience to allow both the initiation and fetching the
  /// future to be compactly encoded in a return statement's expression.
  final js.Expression asyncStart;

  /// Function called by the async function to simulate an `await`
  /// expression. It is called with:
  ///
  /// - The value to await
  /// - The body function [bodyName]
  final js.Expression asyncAwait;

  /// Function called by the async function to simulate a return.
  /// It is called with:
  ///
  /// - The value to return
  /// - The completer object [completer]
  final js.Expression asyncReturn;

  /// Function called by the async function to simulate a rethrow.
  /// It is called with:
  ///
  /// - The value containing the exception and stack
  /// - The completer object [completer]
  final js.Expression asyncRethrow;

  /// Constructor used to initialize the [completer] variable.
  ///
  /// Specific to async methods.
  final js.Expression completerFactory;
  List<js.Expression>? completerFactoryTypeArguments;

  final js.Expression wrapBody;

  AsyncRewriter(
    DiagnosticReporter reporter,
    Spannable? spannable, {
    required this.asyncStart,
    required this.asyncAwait,
    required this.asyncReturn,
    required this.asyncRethrow,
    required this.completerFactory,
    required this.completerFactoryTypeArguments,
    required this.wrapBody,
    required String Function(String proposedName) safeVariableName,
    required js.Name bodyName,
  }) : super(reporter, spannable, safeVariableName, bodyName);

  @override
  void addYield(
    js.DartYield node,
    js.Expression expression,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    reporter.internalError(spannable, "Yield in non-generating async function");
  }

  @override
  void addErrorExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    if (!hasHandlerLabels) return; // rethrow handled in method boilerplate.
    beginLabel(rethrowLabel);
    js.Expression thenHelperCall = js
        .js("#thenHelper(#errorStack.at(-1), #completer)", {
          "thenHelper": asyncRethrow,
          "errorStack": errorStack,
          "completer": completer,
        })
        .withSourceInformation(sourceInformation);
    addStatement(
      js.Return(thenHelperCall).withSourceInformation(sourceInformation),
    );
  }

  /// Returning from an async method calls [asyncStarHelper] with the result.
  /// (the result might have been stored in [returnValue] by some finally
  /// block).
  @override
  void addSuccessExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    if (analysis.hasExplicitReturns) {
      beginLabel(exitLabel!);
    } else {
      addStatement(js.Comment("implicit return"));
    }

    js.Expression runtimeHelperCall = js
        .js("#runtimeHelper(#returnValue, #completer)", {
          "runtimeHelper": asyncReturn,
          "returnValue":
              analysis.hasExplicitReturns ? returnValue : js.LiteralNull(),
          "completer": completer,
        })
        .withSourceInformation(sourceInformation);
    addStatement(
      js.Return(runtimeHelperCall).withSourceInformation(sourceInformation),
    );
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations(
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    List<js.VariableInitialization> variables = [];
    variables.add(
      _makeVariableInitializer(
        completer,
        js
            .js('#(#)', [completerFactory, completerFactoryTypeArguments])
            .withSourceInformation(sourceInformation),
        sourceInformation,
      ),
    );
    if (analysis.hasExplicitReturns) {
      variables.add(
        _makeVariableInitializer(returnValue, null, sourceInformation),
      );
    }
    return variables;
  }

  @override
  void initializeNames() {
    completerName = freshName("completer");
    completerFactoryTypeArguments = processTypeArguments(
      completerFactoryTypeArguments,
    );
  }

  @override
  js.Statement awaitStatement(
    js.Expression value,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    js.Expression asyncHelperCall = js
        .js("#asyncHelper(#value, #bodyName)", {
          "asyncHelper": asyncAwait,
          "value": value,
          "bodyName": bodyName,
        })
        .withSourceInformation(sourceInformation);
    return js.Return(asyncHelperCall).withSourceInformation(sourceInformation);
  }

  @override
  js.Fun finishFunction(
    List<js.Parameter> parameters,
    List<js.Parameter> typeParameters,
    js.Statement rewrittenBody,
    js.VariableDeclarationList variableDeclarations,
    js.JavaScriptNodeSourceInformation? functionSourceInformation,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
  ) {
    js.Statement errorCheck;
    if (hasHandlerLabels) {
      errorCheck = js.js
          .statement(
            """
            if (#errorCode === #ERROR) {
              #errorStack.push(#result);
              #goto = #handler;
            }""",
            {
              "errorCode": errorCodeName,
              "ERROR": js.number(status_codes.ERROR),
              "errorStack": errorStack,
              "result": resultName,
              "goto": goto,
              "handler": handler,
            },
          )
          .withSourceInformation(bodySourceInformation);
    } else {
      js.Expression asyncRethrowCall = js
          .js("#asyncRethrow(#result, #completer)", {
            "result": resultName,
            "asyncRethrow": asyncRethrow,
            "completer": completer,
          })
          .withSourceInformation(bodySourceInformation);
      js.Statement returnAsyncRethrow = js.Return(
        asyncRethrowCall,
      ).withSourceInformation(bodySourceInformation);
      errorCheck = js.js
          .statement(
            """
            if (#errorCode === #ERROR)
              #returnAsyncRethrow;
            """,
            {
              "errorCode": errorCodeName,
              "ERROR": js.number(status_codes.ERROR),
              "returnAsyncRethrow": returnAsyncRethrow,
            },
          )
          .withSourceInformation(bodySourceInformation);
    }

    js.Expression innerFunction = js
        .js(
          """
      function (#errorCode, #result) {
        #errorCheck;
        #rewrittenBody;
      }""",
          {
            "errorCode": errorCodeName,
            "result": resultName,
            "errorCheck": errorCheck,
            "rewrittenBody": rewrittenBody,
          },
        )
        .withSourceInformation(functionSourceInformation);
    js.Expression asyncStartCall = js
        .js("#asyncStart(#bodyName, #completer)", {
          "asyncStart": asyncStart,
          "bodyName": bodyName,
          "completer": completer,
        })
        .withSourceInformation(bodySourceInformation);
    js.Statement returnAsyncStart = js.Return(
      asyncStartCall,
    ).withSourceInformation(bodySourceInformation);
    js.Expression wrapBodyCall = js
        .js("#wrapBody(#innerFunction)", {
          "wrapBody": wrapBody,
          "innerFunction": innerFunction,
        })
        .withSourceInformation(bodySourceInformation);
    return js
            .js(
              """
        function (#parameters, #typeParameters) {
          #variableDeclarations;
          var #bodyName = #wrapBodyCall;
          #returnAsyncStart;
        }""",
              {
                "parameters": parameters,
                "typeParameters": typeParameters,
                "variableDeclarations": variableDeclarations,
                "bodyName": bodyName,
                "wrapBodyCall": wrapBodyCall,
                "returnAsyncStart": returnAsyncStart,
              },
            )
            .withSourceInformation(functionSourceInformation)
        as js.Fun;
  }
}

class SyncStarRewriter extends AsyncRewriterBase {
  @override
  bool get isSyncStar => true;

  /// A parameter to the [bodyName] function that passes the controlling
  /// `_SyncStarIterator`. This parameter is used to update the state of the
  /// iterator.
  late final String iteratorName;

  /// Property of the iterator that contains the current value.
  final js.Expression iteratorCurrentValueProperty;

  /// Property of the iterator that contains the uncaught exeception.
  final js.Expression iteratorDatumProperty;

  /// Property of the iterator that is bound to the `_yieldStar` method.
  final js.Expression yieldStarSelector;

  SyncStarRewriter(
    DiagnosticReporter diagnosticListener,
    Spannable? spannable, {
    required this.iteratorCurrentValueProperty,
    required this.iteratorDatumProperty,
    required this.yieldStarSelector,
    required String Function(String proposedName) safeVariableName,
    required js.Name bodyName,
  }) : super(diagnosticListener, spannable, safeVariableName, bodyName);

  /// Translates a yield/yield* in an sync*.
  @override
  void addYield(
    js.DartYield node,
    js.Expression expression,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    if (node.hasStar) {
      // ``yield* expression` is translated to:
      //
      //     return $iterator._yieldStar(expression);
      //
      // The `_yieldStar` method updates the state of the Iterator to 'enter'
      // the expression and returns the SYNC_STAR_YIELD_STAR status code.
      addStatement(
        js.Return(
          js.Call(
            js.PropertyAccess(js.VariableUse(iteratorName), yieldStarSelector),
            [expression],
          ).withSourceInformation(sourceInformation),
        ).withSourceInformation(sourceInformation),
      );
    } else {
      // `yield expression` is translated to:
      //
      //     return $iterator._current = expression, SYNC_STAR_YIELD;
      //
      // This sets the `_current` field of the Iterator and returns the
      // SYNC_STAR_YIELD status code.
      final store = js.Assignment(
        js.PropertyAccess(
          js.VariableUse(iteratorName),
          iteratorCurrentValueProperty,
        ),
        expression,
      );
      addStatement(
        js.Return(
          js.Binary(',', store, js.number(status_codes.SYNC_STAR_YIELD)),
        ).withSourceInformation(sourceInformation),
      );
    }
  }

  @override
  js.Fun finishFunction(
    List<js.Parameter> parameters,
    List<js.Parameter> typeParameters,
    js.Statement rewrittenBody,
    js.VariableDeclarationList variableDeclarations,
    js.JavaScriptNodeSourceInformation? functionSourceInformation,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
  ) {
    // Each iterator invocation on the iterable should work on its own copy of
    // the parameters.
    // TODO(sigurdm): We only need to do this copying for parameters that are
    // mutated.
    List<js.VariableInitialization> declarations = [];
    List<js.Parameter> renamedParameters = [];
    for (js.Parameter parameter in parameters) {
      String name = parameter.name;
      String renamedName = freshName(name);
      renamedParameters.add(js.Parameter(renamedName));
      declarations.add(
        js.VariableInitialization(
          js.VariableDeclaration(name),
          js.VariableUse(renamedName),
        ),
      );
    }
    js.VariableDeclarationList copyParameters = js.VariableDeclarationList(
      declarations,
    );

    js.Expression pushError = js
        .js("#errorStack.push(#result)", {
          "result": resultName,
          "errorStack": errorStackName,
        })
        .withSourceInformation(bodySourceInformation);
    js.Expression setGoto = js
        .js("#goto = #handler", {"goto": goto, "handler": handler})
        .withSourceInformation(bodySourceInformation);
    js.Statement checkErrorCode = js.js
        .statement(
          """
          if (#errorCode === #ERROR) {
              #pushError;
              #setGoto;
          }""",
          {
            "errorCode": errorCodeName,
            "ERROR": js.number(status_codes.ERROR),
            "pushError": pushError,
            "setGoto": setGoto,
          },
        )
        .withSourceInformation(bodySourceInformation);
    js.Expression innerInnerFunction = js
        .js(
          """
          function #body(#iterator, #errorCode, #result) {
            #checkErrorCode;
            #helperBody;
          }""",
          {
            "helperBody": rewrittenBody,
            "errorCode": errorCodeName,
            "iterator": iteratorName,
            "body": bodyName,
            "result": resultName,
            "checkErrorCode": checkErrorCode,
          },
        )
        .withSourceInformation(functionSourceInformation);
    js.Statement returnInnerInnerFunction = js.Return(
      innerInnerFunction,
    ).withSourceInformation(bodySourceInformation);
    js.Expression innerFunction = js
        .js(
          """
          function () {
            if (#hasParameters) {
              #copyParameters;
            }
            #varDecl;
            #returnInnerInnerFunction;
          }""",
          {
            "hasParameters": parameters.isNotEmpty,
            "copyParameters": copyParameters,
            "varDecl": variableDeclarations,
            "returnInnerInnerFunction": returnInnerInnerFunction,
          },
        )
        .withSourceInformation(functionSourceInformation);
    js.Statement returnInnerFunction = js.Return(
      innerFunction,
    ).withSourceInformation(bodySourceInformation);
    return js
            .js(
              """
          function (#renamedParameters, #typeParameters) {
            if (#needsThis)
              var #self = this;
            #returnInnerFunction;
          }
          """,
              {
                "renamedParameters": renamedParameters,
                "typeParameters": typeParameters,
                "needsThis": analysis.hasThis,
                "self": selfName,
                "returnInnerFunction": returnInnerFunction,
              },
            )
            .withSourceInformation(functionSourceInformation)
        as js.Fun;
  }

  @override
  void addErrorExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    hasHandlerLabels = true; // TODO(sra): Add short form error handler.
    beginLabel(rethrowLabel);
    // Unguarded rethrow is translated to:
    //
    //     return $iterator._datum = exception, SYNC_STAR_UNCAUGHT_EXCEPTION;
    //
    // This stashes the exception on the Iterator and returns the
    // SYNC_STAR_UNCAUGHT_EXCEPTION status code.
    final store = js.Assignment(
      js.PropertyAccess(js.VariableUse(iteratorName), iteratorDatumProperty),
      js.js('#.at(-1)', [errorStack]),
    );
    addStatement(
      js.Return(
        js.Binary(
          ',',
          store,
          js.number(status_codes.SYNC_STAR_UNCAUGHT_EXCEPTION),
        ),
      ).withSourceInformation(sourceInformation),
    );
  }

  /// Returning from a sync* function returns the SYNC_STAR_DONE status code.
  @override
  void addSuccessExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    if (analysis.hasExplicitReturns) {
      beginLabel(exitLabel!);
    } else {
      addStatement(js.Comment("implicit return"));
    }
    addStatement(
      js.Return(
        js.number(status_codes.SYNC_STAR_DONE),
      ).withSourceInformation(sourceInformation),
    );
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations(
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    List<js.VariableInitialization> variables = [];
    return variables;
  }

  @override
  js.Statement awaitStatement(
    js.Expression value,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    throw reporter.internalError(
      spannable,
      "Sync* functions cannot contain await statements.",
    );
  }

  @override
  void initializeNames() {
    iteratorName = freshName('iterator');
  }
}

class AsyncStarRewriter extends AsyncRewriterBase {
  @override
  bool get isAsyncStar => true;

  /// The stack of labels of finally blocks to assign to [next] if the
  /// async* [StreamSubscription] was canceled during a yield.
  js.VariableUse get nextWhenCanceled {
    return js.VariableUse(nextWhenCanceledName);
  }

  late final String nextWhenCanceledName;

  /// The StreamController that controls an async* function.
  late final String controllerName;
  js.VariableUse get controller => js.VariableUse(controllerName);

  /// The function called by an async* function to simulate an await, yield or
  /// yield*.
  ///
  /// For an await/yield/yield* it is called with:
  ///
  /// - The value to await/yieldExpression(value to yield)/
  /// yieldStarExpression(stream to yield)
  /// - The body function [bodyName]
  /// - The controller object [controllerName]
  ///
  /// For a return it is called with:
  ///
  /// - null
  /// - null
  /// - The [controllerName]
  /// - null.
  final js.Expression asyncStarHelper;

  /// Constructor used to initialize the [controllerName] variable.
  ///
  /// Specific to async* methods.
  final js.Expression newController;
  List<js.Expression>? newControllerTypeArguments;

  /// Used to get the `Stream` out of the [controllerName] variable.
  final js.Expression streamOfController;

  /// A JS Expression that creates a marker indicating a 'yield' statement.
  ///
  /// Called with the value to yield.
  final js.Expression yieldExpression;

  /// A JS Expression that creates a marker indication a 'yield*' statement.
  ///
  /// Called with the stream to yield from.
  final js.Expression yieldStarExpression;

  final js.Expression wrapBody;

  AsyncStarRewriter(
    DiagnosticReporter reporter,
    Spannable spannable, {
    required this.asyncStarHelper,
    required this.streamOfController,
    required this.newController,
    required this.newControllerTypeArguments,
    required this.yieldExpression,
    required this.yieldStarExpression,
    required this.wrapBody,
    required String Function(String proposedName) safeVariableName,
    required js.Name bodyName,
  }) : super(reporter, spannable, safeVariableName, bodyName);

  /// Translates a yield/yield* in an async* function.
  ///
  /// yield/yield* in an async* function is translated much like the `await` is
  /// translated in [visitAwait], only the object is wrapped in a
  /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper]
  /// distinguish them.
  /// Also [nextWhenCanceled] is set up to contain the finally blocks that
  /// must be run in case the stream was canceled.
  @override
  void addYield(
    js.DartYield node,
    js.Expression expression,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    // Find all the finally blocks that should be performed if the stream is
    // canceled during the yield.
    List<int> enclosingFinallyLabels = [
      // At the bottom of the stack is the return label.
      exitLabel!,
      for (final node in jumpTargets)
        if (finallyLabels[node] != null) finallyLabels[node]!,
    ];

    addStatement(
      js.js
          .statement("# = #;", [
            nextWhenCanceled,
            js.ArrayInitializer(enclosingFinallyLabels.map(js.number).toList()),
          ])
          .withSourceInformation(sourceInformation),
    );
    js.Expression yieldExpressionCall = js
        .js("#yieldExpression(#expression)", {
          "yieldExpression":
              node.hasStar ? yieldStarExpression : yieldExpression,
          "expression": expression,
        })
        .withSourceInformation(sourceInformation);
    js.Expression asyncStarHelperCall = js
        .js("#asyncStarHelper(#yieldExpressionCall, #bodyName, #controller)", {
          "asyncStarHelper": asyncStarHelper,
          "yieldExpressionCall": yieldExpressionCall,
          "bodyName": bodyName,
          "controller": controllerName,
        })
        .withSourceInformation(sourceInformation);
    addStatement(
      js.Return(asyncStarHelperCall).withSourceInformation(sourceInformation),
    );
  }

  @override
  js.Fun finishFunction(
    List<js.Parameter> parameters,
    List<js.Parameter> typeParameters,
    js.Statement rewrittenBody,
    js.VariableDeclarationList variableDeclarations,
    js.JavaScriptNodeSourceInformation? functionSourceInformation,
    js.JavaScriptNodeSourceInformation? bodySourceInformation,
  ) {
    js.Expression updateNext = js
        .js("#next = #nextWhenCanceled", {
          "next": next,
          "nextWhenCanceled": nextWhenCanceled,
        })
        .withSourceInformation(bodySourceInformation);
    js.Expression callPop = js
        .js("#next.pop()", {"next": next})
        .withSourceInformation(bodySourceInformation);
    js.Expression gotoCancelled = js
        .js("#goto = #callPop", {"goto": goto, "callPop": callPop})
        .withSourceInformation(bodySourceInformation);
    js.Expression pushError = js
        .js("#errorStack.push(#result)", {
          "errorStack": errorStack,
          "result": resultName,
        })
        .withSourceInformation(bodySourceInformation);
    js.Expression gotoError = js
        .js("#goto = #handler", {"goto": goto, "handler": handler})
        .withSourceInformation(bodySourceInformation);
    js.Statement breakStatement = js.Break(
      null,
    ).withSourceInformation(bodySourceInformation);
    js.Statement switchCase = js.js
        .statement(
          """
        switch (#errorCode) {
          case #STREAM_WAS_CANCELED:
            #updateNext;
            #gotoCancelled;
            #break;
          case #ERROR:
            #pushError;
            #gotoError;
        }""",
          {
            "errorCode": errorCodeName,
            "STREAM_WAS_CANCELED": js.number(status_codes.STREAM_WAS_CANCELED),
            "updateNext": updateNext,
            "gotoCancelled": gotoCancelled,
            "break": breakStatement,
            "ERROR": js.number(status_codes.ERROR),
            "pushError": pushError,
            "gotoError": gotoError,
          },
        )
        .withSourceInformation(bodySourceInformation);
    js.Statement ifError = js.js
        .statement(
          """
        if (#errorCode === #ERROR) {
          #pushError;
          #gotoError;
        }""",
          {
            "errorCode": errorCodeName,
            "ERROR": js.number(status_codes.ERROR),
            "pushError": pushError,
            "gotoError": gotoError,
          },
        )
        .withSourceInformation(bodySourceInformation);
    js.Statement ifHasYield = js.js
        .statement(
          """
        if (#hasYield) {
          #switchCase
        } else {
          #ifError;
        }
    """,
          {
            "hasYield": analysis.hasYield,
            "switchCase": switchCase,
            "ifError": ifError,
          },
        )
        .withSourceInformation(bodySourceInformation);
    js.Expression innerFunction = js
        .js(
          """
        function (#errorCode, #result) {
          #ifHasYield;
          #rewrittenBody;
        }""",
          {
            "errorCode": errorCodeName,
            "result": resultName,
            "ifHasYield": ifHasYield,
            "rewrittenBody": rewrittenBody,
          },
        )
        .withSourceInformation(functionSourceInformation);
    js.Expression wrapBodyCall = js
        .js("#wrapBody(#innerFunction)", {
          "wrapBody": wrapBody,
          "innerFunction": innerFunction,
        })
        .withSourceInformation(bodySourceInformation);
    js.Statement declareBodyName = js.js
        .statement("var #bodyName = #wrapBodyCall;", {
          "bodyName": bodyName,
          "wrapBodyCall": wrapBodyCall,
        })
        .withSourceInformation(bodySourceInformation);
    js.Expression streamOfControllerCall = js
        .js("#streamOfController(#controller)", {
          "streamOfController": streamOfController,
          "controller": controllerName,
        })
        .withSourceInformation(bodySourceInformation);
    js.Statement returnStreamOfControllerCall = js.Return(
      streamOfControllerCall,
    ).withSourceInformation(bodySourceInformation);
    return js
            .js(
              """
        function (#parameters, #typeParameters) {
          #declareBodyName;
          #variableDeclarations;
          #returnStreamOfControllerCall;
        }""",
              {
                "parameters": parameters,
                "typeParameters": typeParameters,
                "declareBodyName": declareBodyName,
                "variableDeclarations": variableDeclarations,
                "returnStreamOfControllerCall": returnStreamOfControllerCall,
              },
            )
            .withSourceInformation(functionSourceInformation)
        as js.Fun;
  }

  @override
  void addErrorExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    hasHandlerLabels = true;
    beginLabel(rethrowLabel);
    js.Expression asyncHelperCall = js
        .js("#asyncHelper(#errorStack.at(-1), #errorCode, #controller)", {
          "asyncHelper": asyncStarHelper,
          "errorCode": js.number(status_codes.ERROR),
          "errorStack": errorStack,
          "controller": controllerName,
        })
        .withSourceInformation(sourceInformation);
    addStatement(
      js.Return(asyncHelperCall).withSourceInformation(sourceInformation),
    );
  }

  /// Returning from an async* function calls the [streamHelper] with an
  /// [endOfIteration] marker.
  @override
  void addSuccessExit(js.JavaScriptNodeSourceInformation? sourceInformation) {
    beginLabel(exitLabel!);

    js.Expression streamHelperCall = js
        .js("#streamHelper(null, #successCode, #controller)", {
          "streamHelper": asyncStarHelper,
          "successCode": js.number(status_codes.SUCCESS),
          "controller": controllerName,
        })
        .withSourceInformation(sourceInformation);
    addStatement(
      js.Return(streamHelperCall).withSourceInformation(sourceInformation),
    );
  }

  @override
  Iterable<js.VariableInitialization> variableInitializations(
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    List<js.VariableInitialization> variables = [];
    variables.add(
      _makeVariableInitializer(
        controller,
        js
            .js('#(#, #)', [
              newController,
              bodyName,
              newControllerTypeArguments,
            ])
            .withSourceInformation(sourceInformation),
        sourceInformation,
      ),
    );
    if (analysis.hasYield) {
      variables.add(
        _makeVariableInitializer(nextWhenCanceled, null, sourceInformation),
      );
    }
    return variables;
  }

  @override
  void initializeNames() {
    controllerName = freshName("controller");
    nextWhenCanceledName = freshName("nextWhenCanceled");
    newControllerTypeArguments = processTypeArguments(
      newControllerTypeArguments,
    );
  }

  @override
  js.Statement awaitStatement(
    js.Expression value,
    js.JavaScriptNodeSourceInformation? sourceInformation,
  ) {
    js.Expression asyncHelperCall = js
        .js("#asyncHelper(#value, #bodyName, #controller)", {
          "asyncHelper": asyncStarHelper,
          "value": value,
          "bodyName": bodyName,
          "controller": controllerName,
        })
        .withSourceInformation(sourceInformation);
    return js.Return(asyncHelperCall).withSourceInformation(sourceInformation);
  }
}

/// Finds out
///
/// - which expressions have yield or await nested in them.
/// - targets of jumps
/// - a set of used names.
/// - if any [This]-expressions are used.
class PreTranslationAnalysis extends js.BaseVisitor<bool> {
  Set<js.Node> hasAwaitOrYield = {};

  Map<js.Node, js.Node> targets = {};
  List<js.Node> loopsAndSwitches = [];
  List<js.LabeledStatement> labelledStatements = [];
  Set<String> usedNames = {};

  bool hasExplicitReturns = false;

  bool hasThis = false;

  bool hasYield = false;

  bool hasFinally = false;

  // The function currently being analyzed.
  late final js.Fun currentFunction;

  // For error messages.
  final Never Function(js.Node) unsupported;

  PreTranslationAnalysis(this.unsupported);

  bool visit(js.Node node) {
    bool containsAwait = node.accept(this);
    if (containsAwait) {
      hasAwaitOrYield.add(node);
    }
    return containsAwait;
  }

  void analyze(js.Fun node) {
    currentFunction = node;
    node.params.forEach(visit);
    visit(node.body);
  }

  @override
  bool visitNode(js.Node node) {
    throw StateError('Node type ${node.runtimeType} not handled: $node');
  }

  @override
  bool visitAccess(js.PropertyAccess node) {
    bool receiver = visit(node.receiver);
    bool selector = visit(node.selector);
    return receiver || selector;
  }

  @override
  bool visitArrayHole(js.ArrayHole node) {
    return false;
  }

  @override
  bool visitArrayInitializer(js.ArrayInitializer node) {
    bool containsAwait = false;
    for (js.Expression element in node.elements) {
      if (visit(element)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitAssignment(js.Assignment node) {
    bool leftHandSide = visit(node.leftHandSide);
    bool value = visit(node.value);
    return leftHandSide || value;
  }

  @override
  bool visitAwait(js.Await node) {
    visit(node.expression);
    return true;
  }

  @override
  bool visitBinary(js.Binary node) {
    bool left = visit(node.left);
    bool right = visit(node.right);
    return left || right;
  }

  @override
  bool visitBlock(js.Block node) {
    bool containsAwait = false;
    for (js.Statement statement in node.statements) {
      if (visit(statement)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitBreak(js.Break node) {
    if (node.targetLabel != null) {
      targets[node] = labelledStatements.lastWhere((
        js.LabeledStatement statement,
      ) {
        return statement.label == node.targetLabel;
      });
    } else {
      targets[node] = loopsAndSwitches.last;
    }
    return false;
  }

  @override
  bool visitCall(js.Call node) {
    bool containsAwait = visit(node.target);
    for (js.Expression argument in node.arguments) {
      if (visit(argument)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitCase(js.Case node) {
    bool expression = visit(node.expression);
    bool body = visit(node.body);
    return expression || body;
  }

  @override
  bool visitCatch(js.Catch node) {
    bool declaration = visit(node.declaration);
    bool body = visit(node.body);
    return declaration || body;
  }

  @override
  bool visitComment(js.Comment node) {
    return false;
  }

  @override
  bool visitConditional(js.Conditional node) {
    bool condition = visit(node.condition);
    bool then = visit(node.then);
    bool otherwise = visit(node.otherwise);
    return condition || then || otherwise;
  }

  @override
  bool visitContinue(js.Continue node) {
    if (node.targetLabel != null) {
      js.LabeledStatement targetLabel = labelledStatements.lastWhere(
        (js.LabeledStatement stm) => stm.label == node.targetLabel,
      );
      targets[node] = targetLabel.body;
    } else {
      targets[node] = loopsAndSwitches.lastWhere(
        (js.Node node) => node is! js.Switch,
      );
    }
    assert(() {
      js.Node? target = targets[node];
      return target is js.Loop ||
          (target is js.LabeledStatement && target.body is js.Loop);
    }());
    return false;
  }

  @override
  bool visitDefault(js.Default node) {
    return visit(node.body);
  }

  @override
  bool visitDo(js.Do node) {
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    bool condition = visit(node.condition);
    loopsAndSwitches.removeLast();
    return body || condition;
  }

  @override
  bool visitEmptyStatement(js.EmptyStatement node) {
    return false;
  }

  @override
  bool visitExpressionStatement(js.ExpressionStatement node) {
    return visit(node.expression);
  }

  @override
  bool visitFor(js.For node) {
    bool init = (node.init == null) ? false : visit(node.init!);
    bool condition = (node.condition == null) ? false : visit(node.condition!);
    bool update = (node.update == null) ? false : visit(node.update!);
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return init || condition || update || body;
  }

  @override
  bool visitForIn(js.ForIn node) {
    bool object = visit(node.object);
    loopsAndSwitches.add(node);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return object || body;
  }

  @override
  bool visitFunctionExpression(js.FunctionExpression node) {
    return false;
  }

  @override
  bool visitFun(js.Fun node) {
    return false;
  }

  @override
  bool visitArrowFunction(js.ArrowFunction node) {
    return false;
  }

  @override
  bool visitFunctionDeclaration(js.FunctionDeclaration node) {
    return false;
  }

  @override
  bool visitIf(js.If node) {
    bool condition = visit(node.condition);
    bool then = visit(node.then);
    bool otherwise = visit(node.otherwise);
    return condition || then || otherwise;
  }

  @override
  bool visitInterpolatedExpression(js.InterpolatedExpression node) {
    unsupported(node);
  }

  @override
  bool visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
    unsupported(node);
  }

  @override
  bool visitInterpolatedLiteral(js.InterpolatedLiteral node) {
    unsupported(node);
  }

  @override
  bool visitInterpolatedParameter(js.InterpolatedParameter node) {
    unsupported(node);
  }

  @override
  bool visitInterpolatedSelector(js.InterpolatedSelector node) {
    unsupported(node);
  }

  @override
  bool visitInterpolatedStatement(js.InterpolatedStatement node) {
    unsupported(node);
  }

  @override
  bool visitLabeledStatement(js.LabeledStatement node) {
    usedNames.add(node.label);
    labelledStatements.add(node);
    bool containsAwait = visit(node.body);
    labelledStatements.removeLast();
    return containsAwait;
  }

  @override
  bool visitDeferredExpression(js.DeferredExpression node) {
    return false;
  }

  @override
  bool visitDeferredStatement(js.DeferredStatement node) {
    unsupported(node);
  }

  @override
  bool visitDeferredNumber(js.DeferredNumber node) {
    return false;
  }

  @override
  bool visitDeferredString(js.DeferredString node) {
    return false;
  }

  @override
  bool visitLiteralBool(js.LiteralBool node) {
    return false;
  }

  @override
  bool visitLiteralExpression(js.LiteralExpression node) {
    unsupported(node);
  }

  @override
  bool visitLiteralNull(js.LiteralNull node) {
    return false;
  }

  @override
  bool visitLiteralNumber(js.LiteralNumber node) {
    return false;
  }

  @override
  bool visitLiteralStatement(js.LiteralStatement node) {
    unsupported(node);
  }

  @override
  bool visitLiteralString(js.LiteralString node) {
    return false;
  }

  @override
  bool visitStringConcatenation(js.StringConcatenation node) {
    return false;
  }

  @override
  bool visitName(js.Name node) {
    return false;
  }

  @override
  bool visitParentheses(js.Parentheses node) {
    return visit(node.enclosed);
  }

  @override
  bool visitNamedFunction(js.NamedFunction node) {
    return false;
  }

  @override
  bool visitNew(js.New node) {
    return visitCall(node);
  }

  @override
  bool visitObjectInitializer(js.ObjectInitializer node) {
    bool containsAwait = false;
    for (js.Property property in node.properties) {
      if (visit(property)) containsAwait = true;
    }
    return containsAwait;
  }

  @override
  bool visitParameter(js.Parameter node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitPostfix(js.Postfix node) {
    return visit(node.argument);
  }

  @override
  bool visitPrefix(js.Prefix node) {
    return visit(node.argument);
  }

  @override
  bool visitProgram(js.Program node) {
    throw "Unexpected";
  }

  @override
  bool visitProperty(js.Property node) {
    return visit(node.value);
  }

  @override
  bool visitMethodDefinition(js.MethodDefinition node) {
    return false;
  }

  @override
  bool visitRegExpLiteral(js.RegExpLiteral node) {
    return false;
  }

  @override
  bool visitReturn(js.Return node) {
    hasExplicitReturns = true;
    targets[node] = currentFunction;
    if (node.value == null) return false;
    return visit(node.value!);
  }

  @override
  bool visitSwitch(js.Switch node) {
    loopsAndSwitches.add(node);
    // TODO(sra): If just the key has an `await` expression, do not transform
    // the body of the switch.
    bool result = visit(node.key);
    for (js.SwitchClause clause in node.cases) {
      if (visit(clause)) result = true;
    }
    loopsAndSwitches.removeLast();
    return result;
  }

  @override
  bool visitThis(js.This node) {
    hasThis = true;
    return false;
  }

  @override
  bool visitThrow(js.Throw node) {
    return visit(node.expression);
  }

  @override
  bool visitTry(js.Try node) {
    if (node.finallyPart != null) hasFinally = true;
    bool body = visit(node.body);
    bool catchPart = (node.catchPart == null) ? false : visit(node.catchPart!);
    bool finallyPart =
        (node.finallyPart == null) ? false : visit(node.finallyPart!);
    return body || catchPart || finallyPart;
  }

  @override
  bool visitVariableDeclaration(js.VariableDeclaration node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitVariableDeclarationList(js.VariableDeclarationList node) {
    bool result = false;
    for (js.VariableInitialization init in node.declarations) {
      if (visit(init)) result = true;
    }
    return result;
  }

  @override
  bool visitVariableInitialization(js.VariableInitialization node) {
    bool leftHandSide = visit(node.declaration);
    bool value = (node.value == null) ? false : visit(node.value!);
    return leftHandSide || value;
  }

  @override
  bool visitVariableUse(js.VariableUse node) {
    usedNames.add(node.name);
    return false;
  }

  @override
  bool visitWhile(js.While node) {
    loopsAndSwitches.add(node);
    bool condition = visit(node.condition);
    bool body = visit(node.body);
    loopsAndSwitches.removeLast();
    return condition || body;
  }

  @override
  bool visitDartYield(js.DartYield node) {
    hasYield = true;
    visit(node.expression);
    return true;
  }
}
