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

import 'package:js_shared/variance.dart';
import 'package:kernel/ast.dart' as ir;

import '../closure.dart';
import '../common.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../ir/closure.dart';
import '../ir/element_map.dart';
import '../js_backend/annotations.dart';
import '../js_model/element_map.dart';
import '../ordered_typeset.dart';
import '../serialization/deferrable.dart';
import '../serialization/serialization.dart';
import '../universe/selector.dart';
import 'class_type_variable_access.dart';
import 'elements.dart';
import 'env.dart';
import 'js_world_builder.dart' show JClosedWorldBuilder;

class ClosureDataImpl implements ClosureData {
  /// Tag used for identifying serialized [ClosureData] objects in a
  /// debugging data stream.
  static const String tag = 'closure-data';

  final JsToElementMap _elementMap;

  /// Map of the scoping information that corresponds to a particular entity.
  final Map<MemberEntity, ScopeInfo> _scopeMap;
  final Deferrable<Map<ir.TreeNode, CapturedScope>> _capturedScopesMap;
  // Indicates the type variables (if any) that are captured in a given
  // Signature function.
  final Deferrable<Map<MemberEntity, CapturedScope>>
  _capturedScopeForSignatureMap;

  final Deferrable<Map<ir.LocalFunction, ClosureRepresentationInfo>>
  _localClosureRepresentationMap;

  final Map<MemberEntity, MemberEntity> _enclosingMembers;

  ClosureDataImpl(
    this._elementMap,
    this._scopeMap,
    Map<ir.TreeNode, CapturedScope> capturedScopesMap,
    Map<MemberEntity, CapturedScope> capturedScopeForSignatureMap,
    Map<ir.LocalFunction, ClosureRepresentationInfo>
    localClosureRepresentationMap,
    this._enclosingMembers,
  ) : _capturedScopesMap = Deferrable.eager(capturedScopesMap),
      _capturedScopeForSignatureMap = Deferrable.eager(
        capturedScopeForSignatureMap,
      ),
      _localClosureRepresentationMap = Deferrable.eager(
        localClosureRepresentationMap,
      );

  ClosureDataImpl._deserialized(
    this._elementMap,
    this._scopeMap,
    this._capturedScopesMap,
    this._capturedScopeForSignatureMap,
    this._localClosureRepresentationMap,
    this._enclosingMembers,
  );

  static Map<ir.TreeNode, CapturedScope> _readCapturedScopesMap(
    DataSourceReader source,
  ) {
    return source.readTreeNodeMap(
      () => CapturedScope.readFromDataSource(source),
    );
  }

  static Map<MemberEntity, CapturedScope> _readCapturedScopeForSignatureMap(
    DataSourceReader source,
  ) {
    return source.readMemberMap(
      (_) => CapturedScope.readFromDataSource(source),
    );
  }

  static Map<ir.LocalFunction, ClosureRepresentationInfo>
  _readLocalClosureRepresentationMap(DataSourceReader source) {
    return source.readTreeNodeMap<ir.LocalFunction, ClosureRepresentationInfo>(
      () => ClosureRepresentationInfo.readFromDataSource(source),
    );
  }

  /// Deserializes a [ClosureData] object from [source].
  factory ClosureDataImpl.readFromDataSource(
    JsToElementMap elementMap,
    DataSourceReader source,
  ) {
    source.begin(tag);
    // TODO(johnniwinther): Support shared [ScopeInfo].
    final scopeMap = source.readMemberMap(
      (MemberEntity member) =>
          source.readDeferrable(ScopeInfo.readFromDataSource),
    );
    final capturedScopesMap = source.readDeferrable(_readCapturedScopesMap);
    final capturedScopeForSignatureMap = source.readDeferrable(
      _readCapturedScopeForSignatureMap,
    );
    final localClosureRepresentationMap = source.readDeferrable(
      _readLocalClosureRepresentationMap,
    );
    Map<MemberEntity, MemberEntity> enclosingMembers = source.readMemberMap(
      (member) => source.readMember(),
    );
    source.end(tag);
    return ClosureDataImpl._deserialized(
      elementMap,
      DeferrableValueMap(scopeMap),
      capturedScopesMap,
      capturedScopeForSignatureMap,
      localClosureRepresentationMap,
      enclosingMembers,
    );
  }

  /// Serializes this [ClosureData] to [sink].
  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeMemberMap(
      _scopeMap,
      (_, ScopeInfo info) =>
          sink.writeDeferrable(() => info.writeToDataSink(sink)),
    );
    sink.writeDeferrable(
      () => sink.writeTreeNodeMap(_capturedScopesMap.loaded(), (
        CapturedScope scope,
      ) {
        scope.writeToDataSink(sink);
      }),
    );
    sink.writeDeferrable(
      () => sink.writeMemberMap(
        _capturedScopeForSignatureMap.loaded(),
        (MemberEntity member, CapturedScope scope) =>
            scope.writeToDataSink(sink),
      ),
    );
    sink.writeDeferrable(
      () => sink.writeTreeNodeMap(_localClosureRepresentationMap.loaded(), (
        ClosureRepresentationInfo info,
      ) {
        info.writeToDataSink(sink);
      }),
    );
    sink.writeMemberMap(_enclosingMembers, (
      MemberEntity member,
      MemberEntity value,
    ) {
      sink.writeMember(value);
    });
    sink.end(tag);
  }

  @override
  ScopeInfo getScopeInfo(MemberEntity entity) {
    // TODO(johnniwinther): Remove this check when constructor bodies a created
    // eagerly with the J-model; a constructor body should have it's own
    // [ClosureRepresentationInfo].
    if (entity is ConstructorBodyEntity) {
      entity = entity.constructor;
    } else if (entity is JParameterStub) {
      entity = entity.target;
    }

    return _scopeMap[entity]!;
  }

  // TODO(efortuna): Eventually capturedScopesMap[node] should always
  // be non-null, and we should just test that with an assert.
  @override
  CapturedScope getCapturedScope(MemberEntity entity) {
    MemberDefinition definition = _elementMap.getMemberDefinition(entity);
    switch (definition.kind) {
      case MemberKind.regular:
      case MemberKind.constructor:
      case MemberKind.constructorBody:
      case MemberKind.closureCall:
        return _capturedScopesMap.loaded()[definition.node] ??
            const CapturedScope();
      case MemberKind.signature:
        return _capturedScopeForSignatureMap.loaded()[entity] ??
            const CapturedScope();
      case MemberKind.parameterStub:
        return const CapturedScope();
      case MemberKind.closureField:
      case MemberKind.generatorBody:
      case MemberKind.recordGetter:
        throw failedAt(entity, "Unexpected member definition $definition");
    }
  }

  @override
  CapturedScope getCapturedBlockScope(ir.Block blockNode) =>
      _capturedScopesMap.loaded()[blockNode] ?? const CapturedScope();

  @override
  // TODO(efortuna): Eventually capturedScopesMap[node] should always
  // be non-null, and we should just test that with an assert.
  CapturedLoopScope getCapturedLoopScope(ir.Node loopNode) =>
      _capturedScopesMap.loaded()[loopNode] as CapturedLoopScope? ??
      const CapturedLoopScope();

  @override
  ClosureRepresentationInfo getClosureInfo(ir.LocalFunction node) =>
      _localClosureRepresentationMap.loaded()[node]!;

  @override
  MemberEntity getEnclosingMember(MemberEntity member) {
    return _enclosingMembers[member] ?? member;
  }
}

/// Closure conversion code using our new Entity model. Closure conversion is
/// necessary because the semantics of closures are slightly different in Dart
/// than JavaScript. Closure conversion is separated out into two phases:
/// generation of a new (temporary) representation to store where variables need
/// to be hoisted/captured up at another level to re-write the closure, and then
/// the code generation phase where we generate elements and/or instructions to
/// represent this new code path.
///
/// For a general explanation of how closure conversion works at a high level,
/// check out:
/// http://siek.blogspot.com/2012/07/essence-of-closure-conversion.html or
/// http://matt.might.net/articles/closure-conversion/.

class ClosureDataBuilder {
  final DiagnosticReporter _reporter;
  final JsToElementMap _elementMap;
  final AnnotationsData _annotationsData;

  /// Map of the scoping information that corresponds to a particular entity.
  final Map<MemberEntity, ScopeInfo> _scopeMap = {};
  final Map<ir.TreeNode, CapturedScope> _capturedScopesMap = {};
  // Indicates the type variables (if any) that are captured in a given
  // Signature function.
  final Map<MemberEntity, CapturedScope> _capturedScopeForSignatureMap = {};

  final Map<ir.LocalFunction, ClosureRepresentationInfo>
  _localClosureRepresentationMap = {};

  final Map<MemberEntity, MemberEntity> _enclosingMembers = {};

  ClosureDataBuilder(this._reporter, this._elementMap, this._annotationsData);

  void _updateScopeBasedOnRtiNeed(
    KernelScopeInfo scope,
    ClosureRtiNeed rtiNeed,
    MemberEntity outermostEntity,
  ) {
    bool includeForRti(Set<VariableUse> useSet) {
      for (VariableUse usage in useSet) {
        switch (usage) {
          case SimpleVariableUse.explicit:
            return true;
          case SimpleVariableUse.implicitCast:
            if (_annotationsData
                .getImplicitDowncastCheckPolicy(outermostEntity)
                .isEmitted) {
              return true;
            }
            break;
          case SimpleVariableUse.localType:
            break;
          case ConstructorTypeArgumentVariableUse(:final member):
            ConstructorEntity constructor = _elementMap.getConstructor(member);
            if (rtiNeed.classNeedsTypeArguments(constructor.enclosingClass)) {
              return true;
            }
            break;
          case StaticTypeArgumentVariableUse(:final procedure):
            FunctionEntity method = _elementMap.getMethod(procedure);
            if (rtiNeed.methodNeedsTypeArguments(method)) {
              return true;
            }
            break;
          case InstanceTypeArgumentVariableUse(:final invocation):
            Selector selector = _elementMap.getSelector(invocation);
            if (rtiNeed.selectorNeedsTypeArguments(selector)) {
              return true;
            }
            break;
          case LocalTypeArgumentVariableUse(
            :final localFunction,
            :final invocation,
          ):
            // TODO(johnniwinther): We should be able to track direct local
            // function invocations and not have to use the selector here.
            Selector selector = _elementMap.getSelector(invocation);
            if (rtiNeed.localFunctionNeedsTypeArguments(localFunction) ||
                rtiNeed.selectorNeedsTypeArguments(selector)) {
              return true;
            }
            break;
          case MemberParameterVariableUse(:final member):
            if (_annotationsData
                .getParameterCheckPolicy(outermostEntity)
                .isEmitted) {
              return true;
            } else {
              FunctionEntity method = _elementMap.getMethod(
                member as ir.Procedure,
              );
              if (rtiNeed.methodNeedsSignature(method)) {
                return true;
              }
              if (rtiNeed.methodNeedsTypeArguments(method)) {
                // Stubs generated for this method might make use of this type
                // parameter for default type arguments.
                return true;
              }
            }
            break;
          case LocalParameterVariableUse(:final localFunction):
            if (_annotationsData
                .getParameterCheckPolicy(outermostEntity)
                .isEmitted) {
              return true;
            } else if (rtiNeed.localFunctionNeedsSignature(localFunction)) {
              return true;
            } else if (rtiNeed.localFunctionNeedsTypeArguments(localFunction)) {
              // Stubs generated for this local function might make use of this
              // type parameter for default type arguments.
              return true;
            }
            break;
          case MemberReturnTypeVariableUse(:final member):
            FunctionEntity method = _elementMap.getMethod(
              member as ir.Procedure,
            );
            if (rtiNeed.methodNeedsSignature(method)) {
              return true;
            }
            break;
          case LocalReturnTypeVariableUse(:final localFunction):
            if (localFunction.function.asyncMarker != ir.AsyncMarker.Sync) {
              // The Future/Iterator/Stream implementation requires the type.
              return true;
            }
            if (rtiNeed.localFunctionNeedsSignature(localFunction)) {
              return true;
            }
            break;
          case SimpleVariableUse.fieldType:
            if (_annotationsData
                .getParameterCheckPolicy(outermostEntity)
                .isEmitted) {
              return true;
            }
            break;
          case SimpleVariableUse.listLiteral:
            if (rtiNeed.classNeedsTypeArguments(
              _elementMap.commonElements.jsArrayClass,
            )) {
              return true;
            }
            break;
          case SimpleVariableUse.setLiteral:
            if (rtiNeed.classNeedsTypeArguments(
              _elementMap.commonElements.setLiteralClass,
            )) {
              return true;
            }
            break;
          case SimpleVariableUse.mapLiteral:
            if (rtiNeed.classNeedsTypeArguments(
              _elementMap.commonElements.mapLiteralClass,
            )) {
              return true;
            }
            break;
          case InstantiationTypeArgumentVariableUse(:final instantiation):
            // TODO(johnniwinther): Use the static type of the expression.
            if (rtiNeed.instantiationNeedsTypeArguments(
              null,
              instantiation.typeArguments.length,
            )) {
              return true;
            }
            break;
        }
      }
      return false;
    }

    if (includeForRti(scope.thisUsedAsFreeVariableIfNeedsRti)) {
      scope.thisUsedAsFreeVariable = true;
    }
    scope.freeVariablesForRti.forEach((
      TypeVariableTypeWithContext typeVariable,
      Set<VariableUse> useSet,
    ) {
      if (includeForRti(useSet)) {
        scope.freeVariables.add(typeVariable);
      }
    });
  }

  ClosureData createClosureEntities(
    JClosedWorldBuilder closedWorldBuilder,
    Map<MemberEntity, ClosureScopeModel> closureModels,
    ClosureRtiNeed rtiNeed,
    List<FunctionEntity> callMethods,
  ) {
    void processModel(MemberEntity member, ClosureScopeModel model) {
      Map<ir.VariableDeclaration, JContextField> allBoxedVariables = _elementMap
          .makeContextContainer(model.scopeInfo!, member);
      _scopeMap[member] = JsScopeInfo.from(
        allBoxedVariables,
        model.scopeInfo!,
        member.enclosingClass,
      );

      model.capturedScopesMap.forEach((
        ir.Node node,
        KernelCapturedScope scope,
      ) {
        Map<ir.VariableDeclaration, JContextField> boxedVariables = _elementMap
            .makeContextContainer(scope, member);
        _updateScopeBasedOnRtiNeed(scope, rtiNeed, member);

        if (scope is KernelCapturedLoopScope) {
          _capturedScopesMap[node as ir.TreeNode] = JsCapturedLoopScope.from(
            boxedVariables,
            scope,
            member.enclosingClass,
          );
        } else {
          _capturedScopesMap[node as ir.TreeNode] = JsCapturedScope.from(
            boxedVariables,
            scope,
            member.enclosingClass,
          );
        }
        allBoxedVariables.addAll(boxedVariables);
      });

      Map<ir.LocalFunction, KernelScopeInfo> closuresToGenerate =
          model.closuresToGenerate;
      for (ir.LocalFunction node in closuresToGenerate.keys) {
        ir.FunctionNode functionNode = node.function;
        JsClosureClassInfo closureClassInfo = _produceSyntheticElements(
          closedWorldBuilder,
          member,
          functionNode,
          closuresToGenerate[node]!,
          allBoxedVariables,
          rtiNeed,
          createSignatureMethod: rtiNeed.localFunctionNeedsSignature(
            functionNode.parent as ir.LocalFunction,
          ),
        );
        // Add also for the call method.
        _scopeMap[closureClassInfo.callMethod!] = closureClassInfo;
        if (closureClassInfo.signatureMethod != null) {
          _scopeMap[closureClassInfo.signatureMethod!] = closureClassInfo;

          // Set up capturedScope for signature method. This is distinct from
          // _capturedScopesMap because there is no corresponding ir.Node for
          // the signature.
          if (rtiNeed.localFunctionNeedsSignature(
                functionNode.parent as ir.LocalFunction,
              ) &&
              model.capturedScopesMap[functionNode] != null) {
            KernelCapturedScope capturedScope =
                model.capturedScopesMap[functionNode]!;
            assert(capturedScope is! KernelCapturedLoopScope);
            KernelCapturedScope signatureCapturedScope =
                KernelCapturedScope.forSignature(capturedScope);
            _updateScopeBasedOnRtiNeed(signatureCapturedScope, rtiNeed, member);
            _capturedScopeForSignatureMap[closureClassInfo.signatureMethod!] =
                JsCapturedScope.from(
                  {},
                  signatureCapturedScope,
                  member.enclosingClass,
                );
          }
        }
        callMethods.add(closureClassInfo.callMethod!);
      }
    }

    closureModels.forEach((MemberEntity member, ClosureScopeModel model) {
      _reporter.withCurrentElement(member, () {
        processModel(member, model);
      });
    });
    return ClosureDataImpl(
      _elementMap,
      _scopeMap,
      _capturedScopesMap,
      _capturedScopeForSignatureMap,
      _localClosureRepresentationMap,
      _enclosingMembers,
    );
  }

  /// Given what variables are captured at each point, construct closure classes
  /// with fields containing the captured variables to replicate the Dart
  /// closure semantics in JS. If this closure captures any variables (meaning
  /// the closure accesses a variable that gets accessed at some point), then
  /// boxForCapturedVariables stores the local context for those variables.
  /// If no variables are captured, this parameter is null.
  JsClosureClassInfo _produceSyntheticElements(
    JClosedWorldBuilder closedWorldBuilder,
    MemberEntity member,
    ir.FunctionNode node,
    KernelScopeInfo info,
    Map<ir.VariableDeclaration, JContextField> boxedVariables,
    ClosureRtiNeed rtiNeed, {
    required bool createSignatureMethod,
  }) {
    _updateScopeBasedOnRtiNeed(info, rtiNeed, member);
    JsClosureClassInfo closureClassInfo = closedWorldBuilder.buildClosureClass(
      member,
      node,
      member.library as JLibrary,
      boxedVariables,
      info,
      createSignatureMethod: createSignatureMethod,
    );

    // We want the original declaration where that function is used to point
    // to the correct closure class.
    _enclosingMembers[closureClassInfo.callMethod!] = member;
    if (closureClassInfo.signatureMethod != null) {
      _enclosingMembers[closureClassInfo.signatureMethod!] = member;
    }
    if (node.parent is ir.Member) {
      assert(_elementMap.getMember(node.parent as ir.Member) == member);
    } else {
      assert(node.parent is ir.LocalFunction);
      _localClosureRepresentationMap[node.parent as ir.LocalFunction] =
          closureClassInfo;
    }
    return closureClassInfo;
  }
}

class JsScopeInfo extends ScopeInfo {
  /// Tag used for identifying serialized [JsScopeInfo] objects in a
  /// debugging data stream.
  static const String tag = 'scope-info';

  final Iterable<ir.VariableDeclaration> _localsUsedInTryOrSync;

  Set<Local>? _localsUsedInTryOrSyncCache;

  @override
  final Local? thisLocal;

  final Map<ir.VariableDeclaration, JContextField> _boxedVariables;

  Map<Local, JContextField>? _boxedVariablesCache;

  JsScopeInfo.internal(
    this._localsUsedInTryOrSync,
    this.thisLocal,
    this._boxedVariables,
  );

  JsScopeInfo.from(
    this._boxedVariables,
    KernelScopeInfo info,
    ClassEntity? enclosingClass,
  ) : thisLocal = info.hasThisLocal ? ThisLocal(enclosingClass!) : null,
      _localsUsedInTryOrSync = info.localsUsedInTryOrSync;

  void _ensureBoxedVariableCache(KernelToLocalsMap localsMap) {
    if (_boxedVariablesCache == null) {
      if (_boxedVariables.isEmpty) {
        _boxedVariablesCache = const {};
      } else {
        final cache = <Local, JContextField>{};
        _boxedVariables.forEach((
          ir.VariableDeclaration node,
          JContextField field,
        ) {
          cache[localsMap.getLocalVariable(node)] = field;
        });
        _boxedVariablesCache = cache;
      }
    }
  }

  @override
  void forEachBoxedVariable(
    KernelToLocalsMap localsMap,
    void Function(Local local, FieldEntity field) f,
  ) {
    _ensureBoxedVariableCache(localsMap);
    _boxedVariablesCache!.forEach(f);
  }

  @override
  bool localIsUsedInTryOrSync(KernelToLocalsMap localsMap, Local variable) {
    if (_localsUsedInTryOrSyncCache == null) {
      if (_localsUsedInTryOrSync.isEmpty) {
        _localsUsedInTryOrSyncCache = const {};
      } else {
        _localsUsedInTryOrSyncCache = {};
        for (ir.VariableDeclaration node in _localsUsedInTryOrSync) {
          _localsUsedInTryOrSyncCache!.add(localsMap.getLocalVariable(node));
        }
      }
    }
    return _localsUsedInTryOrSyncCache!.contains(variable);
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('this=$thisLocal,');
    sb.write('localsUsedInTryOrSync={${_localsUsedInTryOrSync.join(', ')}}');
    return sb.toString();
  }

  @override
  bool isBoxedVariable(KernelToLocalsMap localsMap, Local variable) {
    _ensureBoxedVariableCache(localsMap);
    return _boxedVariablesCache!.containsKey(variable);
  }

  factory JsScopeInfo.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Iterable<ir.VariableDeclaration> localsUsedInTryOrSync = source
        .readTreeNodes<ir.VariableDeclaration>();
    Local? thisLocal = source.readLocalOrNull();
    Map<ir.VariableDeclaration, JContextField> boxedVariables = source
        .readTreeNodeMap<ir.VariableDeclaration, JContextField>(
          () => source.readMember() as JContextField,
        );
    source.end(tag);
    if (boxedVariables.isEmpty) boxedVariables = const {};
    return JsScopeInfo.internal(
      localsUsedInTryOrSync,
      thisLocal,
      boxedVariables,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ScopeInfoKind.scopeInfo);
    sink.begin(tag);
    sink.writeTreeNodes(_localsUsedInTryOrSync);
    sink.writeLocalOrNull(thisLocal);
    sink.writeTreeNodeMap(_boxedVariables, sink.writeMember);
    sink.end(tag);
  }
}

class JsCapturedScope extends JsScopeInfo implements CapturedScope {
  /// Tag used for identifying serialized [JsCapturedScope] objects in a
  /// debugging data stream.
  static const String tag = 'captured-scope';

  @override
  final Local? contextBox;

  JsCapturedScope.internal(
    super.localsUsedInTryOrSync,
    super.thisLocal,
    super.boxedVariables,
    this.contextBox,
  ) : super.internal();

  JsCapturedScope.from(
    super.boxedVariables,
    super.capturedScope,
    super.enclosingClass,
  ) : contextBox = boxedVariables.isNotEmpty
          ? boxedVariables.values.first.box
          : null,
      super.from();

  @override
  bool get requiresContextBox => _boxedVariables.isNotEmpty;

  factory JsCapturedScope.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Iterable<ir.VariableDeclaration> localsUsedInTryOrSync = source
        .readTreeNodes<ir.VariableDeclaration>();
    Local? thisLocal = source.readLocalOrNull();
    Map<ir.VariableDeclaration, JContextField> boxedVariables = source
        .readTreeNodeMap<ir.VariableDeclaration, JContextField>(
          () => source.readMember() as JContextField,
        );
    Local? context = source.readLocalOrNull();
    source.end(tag);
    return JsCapturedScope.internal(
      localsUsedInTryOrSync,
      thisLocal,
      boxedVariables,
      context,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ScopeInfoKind.capturedScope);
    sink.begin(tag);
    sink.writeTreeNodes(_localsUsedInTryOrSync);
    sink.writeLocalOrNull(thisLocal);
    sink.writeTreeNodeMap(_boxedVariables, sink.writeMember);
    sink.writeLocalOrNull(contextBox);
    sink.end(tag);
  }
}

class JsCapturedLoopScope extends JsCapturedScope implements CapturedLoopScope {
  /// Tag used for identifying serialized [JsCapturedLoopScope] objects in a
  /// debugging data stream.
  static const String tag = 'captured-loop-scope';

  final List<ir.VariableDeclaration> _boxedLoopVariables;

  JsCapturedLoopScope.internal(
    super.localsUsedInTryOrSync,
    super.thisLocal,
    super.boxedVariables,
    super.context,
    this._boxedLoopVariables,
  ) : super.internal();

  JsCapturedLoopScope.from(
    super.boxedVariables,
    KernelCapturedLoopScope super.capturedScope,
    super.enclosingClass,
  ) : _boxedLoopVariables = capturedScope.boxedLoopVariables,
      super.from();

  @override
  bool get hasBoxedLoopVariables => _boxedLoopVariables.isNotEmpty;

  factory JsCapturedLoopScope.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Iterable<ir.VariableDeclaration> localsUsedInTryOrSync = source
        .readTreeNodes<ir.VariableDeclaration>();
    Local? thisLocal = source.readLocalOrNull();
    Map<ir.VariableDeclaration, JContextField> boxedVariables = source
        .readTreeNodeMap<ir.VariableDeclaration, JContextField>(
          () => source.readMember() as JContextField,
        );
    Local? context = source.readLocalOrNull();
    List<ir.VariableDeclaration> boxedLoopVariables = source
        .readTreeNodes<ir.VariableDeclaration>();
    source.end(tag);
    return JsCapturedLoopScope.internal(
      localsUsedInTryOrSync,
      thisLocal,
      boxedVariables,
      context,
      boxedLoopVariables,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ScopeInfoKind.capturedLoopScope);
    sink.begin(tag);
    sink.writeTreeNodes(_localsUsedInTryOrSync);
    sink.writeLocalOrNull(thisLocal);
    sink.writeTreeNodeMap(_boxedVariables, sink.writeMember);
    sink.writeLocalOrNull(contextBox);
    sink.writeTreeNodes(_boxedLoopVariables);
    sink.end(tag);
  }

  @override
  List<Local> getBoxedLoopVariables(KernelToLocalsMap localsMap) {
    List<Local> locals = [];
    for (ir.VariableDeclaration boxedLoopVariable in _boxedLoopVariables) {
      locals.add(localsMap.getLocalVariable(boxedLoopVariable));
    }
    return locals;
  }
}

// TODO(johnniwinther): Add unittest for the computed [ClosureClass].
class JsClosureClassInfo extends JsScopeInfo
    implements ClosureRepresentationInfo {
  /// Tag used for identifying serialized [JsClosureClassInfo] objects in a
  /// debugging data stream.
  static const String tag = 'closure-representation-info';

  @override
  JFunction? callMethod;

  @override
  JSignatureMethod? signatureMethod;

  /// The local used for this closure, if it is an anonymous closure, i.e.
  /// an `ir.FunctionExpression`.
  final Local? _closureEntity;

  /// The local variable that defines this closure, if it is a local function
  /// declaration.
  final ir.VariableDeclaration? _closureEntityVariable;

  @override
  final JClass closureClassEntity;

  final Map<ir.VariableDeclaration, JField> _variableToFieldMap;
  final Map<JTypeVariable, JField> _typeVariableToFieldMap;
  final Map<Local, JField> _localToFieldMap;
  Map<JField, Local>? _fieldToLocalsMap;

  JsClosureClassInfo.internal(
    super.localsUsedInTryOrSync,
    super.thisLocal,
    super.boxedVariables,
    this.callMethod,
    this.signatureMethod,
    this._closureEntity,
    this._closureEntityVariable,
    this.closureClassEntity,
    this._variableToFieldMap,
    this._typeVariableToFieldMap,
    this._localToFieldMap,
  ) : super.internal();

  JsClosureClassInfo.fromScopeInfo(
    this.closureClassEntity,
    ir.FunctionNode closureSourceNode,
    Map<ir.VariableDeclaration, JContextField> boxedVariables,
    KernelScopeInfo info,
    ClassEntity? enclosingClass,
    this._closureEntity,
    this._closureEntityVariable,
  ) : _variableToFieldMap = {},
      _typeVariableToFieldMap = {},
      _localToFieldMap = {},
      super.from(boxedVariables, info, enclosingClass);

  factory JsClosureClassInfo.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Iterable<ir.VariableDeclaration> localsUsedInTryOrSync = source
        .readTreeNodes<ir.VariableDeclaration>();
    Local? thisLocal = source.readLocalOrNull();
    Map<ir.VariableDeclaration, JContextField> boxedVariables = source
        .readTreeNodeMap<ir.VariableDeclaration, JContextField>(
          () => source.readMember() as JContextField,
        );
    JFunction callMethod = source.readMember() as JFunction;
    JSignatureMethod? signatureMethod =
        source.readMemberOrNull() as JSignatureMethod?;
    Local? closureEntity = source.readLocalOrNull();
    ir.VariableDeclaration? closureEntityVariable =
        source.readTreeNodeOrNull() as ir.VariableDeclaration?;
    JClass closureClassEntity = source.readClass() as JClass;
    Map<ir.VariableDeclaration, JField> localToFieldMap = source
        .readTreeNodeMap<ir.VariableDeclaration, JField>(
          () => source.readMember() as JField,
        );
    Map<JTypeVariable, JField> typeVariableToFieldMap = source
        .readTypeVariableMap<JTypeVariable, JField>(
          () => source.readMember() as JField,
        );
    Map<Local, JField> thisLocalToFieldMap = source.readLocalMap(
      () => source.readMember() as JField,
    );
    source.end(tag);
    if (boxedVariables.isEmpty) boxedVariables = const {};
    if (localToFieldMap.isEmpty) localToFieldMap = const {};
    return JsClosureClassInfo.internal(
      localsUsedInTryOrSync,
      thisLocal,
      boxedVariables,
      callMethod,
      signatureMethod,
      closureEntity,
      closureEntityVariable,
      closureClassEntity,
      localToFieldMap,
      typeVariableToFieldMap,
      thisLocalToFieldMap,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ScopeInfoKind.closureRepresentationInfo);
    sink.begin(tag);
    sink.writeTreeNodes(_localsUsedInTryOrSync);
    sink.writeLocalOrNull(thisLocal);
    sink.writeTreeNodeMap(_boxedVariables, sink.writeMember);
    sink.writeMember(callMethod!);
    sink.writeMemberOrNull(signatureMethod);
    sink.writeLocalOrNull(_closureEntity);
    sink.writeTreeNodeOrNull(_closureEntityVariable);
    sink.writeClass(closureClassEntity);
    sink.writeTreeNodeMap(_variableToFieldMap, sink.writeMember);
    sink.writeTypeVariableMap(_typeVariableToFieldMap, sink.writeMember);
    sink.writeLocalMap(_localToFieldMap, sink.writeMember);
    sink.end(tag);
  }

  bool hasFieldForLocal(Local local) => _localToFieldMap.containsKey(local);

  void registerFieldForLocal(Local local, JField field) {
    assert(_fieldToLocalsMap == null);
    _localToFieldMap[local] = field;
  }

  void registerFieldForVariable(ir.VariableDeclaration node, JField field) {
    assert(_fieldToLocalsMap == null);
    _variableToFieldMap[node] = field;
  }

  bool hasFieldForTypeVariable(JTypeVariable typeVariable) =>
      _typeVariableToFieldMap.containsKey(typeVariable);

  void registerFieldForTypeVariable(JTypeVariable typeVariable, JField field) {
    assert(_fieldToLocalsMap == null);
    _typeVariableToFieldMap[typeVariable] = field;
  }

  void registerFieldForBoxedVariable(
    ir.VariableDeclaration node,
    JField field,
  ) {
    assert(_boxedVariablesCache == null);
    _boxedVariables[node] = field as JContextField;
  }

  void _ensureFieldToLocalsMap(KernelToLocalsMap localsMap) {
    if (_fieldToLocalsMap == null) {
      _fieldToLocalsMap = {};
      _variableToFieldMap.forEach((ir.VariableDeclaration node, JField field) {
        _fieldToLocalsMap![field] = localsMap.getLocalVariable(node);
      });
      _typeVariableToFieldMap.forEach((
        TypeVariableEntity typeVariable,
        JField field,
      ) {
        _fieldToLocalsMap![field] = localsMap.getLocalTypeVariableEntity(
          typeVariable,
        );
      });
      _localToFieldMap.forEach((Local local, JField field) {
        _fieldToLocalsMap![field] = local;
      });
      if (_fieldToLocalsMap!.isEmpty) {
        _fieldToLocalsMap = const {};
      }
    }
  }

  @override
  Local getLocalForField(KernelToLocalsMap localsMap, FieldEntity field) {
    _ensureFieldToLocalsMap(localsMap);
    return _fieldToLocalsMap![field]!;
  }

  @override
  FieldEntity? get thisFieldEntity => _localToFieldMap[thisLocal];

  @override
  void forEachFreeVariable(
    KernelToLocalsMap localsMap,
    void Function(Local variable, JField field) f,
  ) {
    _ensureFieldToLocalsMap(localsMap);
    _ensureBoxedVariableCache(localsMap);
    _fieldToLocalsMap!.forEach((JField field, Local local) {
      f(local, field);
    });
    _boxedVariablesCache!.forEach(f);
  }

  @override
  bool get isClosure => true;

  @override
  Local? getClosureEntity(KernelToLocalsMap localsMap) {
    return _closureEntityVariable != null
        ? localsMap.getLocalVariable(_closureEntityVariable)
        : _closureEntity;
  }
}

abstract class ClosureRtiNeed {
  bool classNeedsTypeArguments(ClassEntity cls);

  bool methodNeedsTypeArguments(FunctionEntity method);

  bool methodNeedsSignature(MemberEntity method);

  bool localFunctionNeedsTypeArguments(ir.LocalFunction node);

  bool localFunctionNeedsSignature(ir.LocalFunction node);

  bool selectorNeedsTypeArguments(Selector selector);

  bool instantiationNeedsTypeArguments(
    FunctionType? functionType,
    int typeArgumentCount,
  );
}

/// A container for variables declared in a particular scope that are accessed
/// elsewhere.
// TODO(johnniwinther): Don't implement JClass. This isn't actually a class.
class JContext extends JClass {
  /// Tag used for identifying serialized [JContext] objects in a debugging data
  /// stream.
  static const String tag = 'context';

  JContext(LibraryEntity library, String name)
    : super(library as JLibrary, name, isAbstract: false);

  factory JContext.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    JLibrary library = source.readLibrary() as JLibrary;
    String name = source.readString();
    source.end(tag);
    return JContext(library, name);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassKind.context);
    sink.begin(tag);
    sink.writeLibrary(library);
    sink.writeString(name);
    sink.end(tag);
  }

  @override
  bool get isClosure => false;

  @override
  String toString() => '${jsElementPrefix}context($name)';
}

/// A variable that has been "boxed" to prevent name shadowing with the original
/// variable and ensure that this variable is updated/read with the most recent
/// value.
class JContextField extends JField {
  /// Tag used for identifying serialized [JContextField] objects in a debugging
  /// data stream.
  static const String tag = 'context-field';

  final BoxLocal box;

  JContextField(String name, this.box, {required bool isConst})
    : super(
        box.container.library as JLibrary,
        box.container as JClass,
        Name(name, box.container.library.canonicalUri),
        isStatic: false,
        isAssignable: true,
        isConst: isConst,
      );

  factory JContextField.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    String name = source.readString();
    final enclosingClass = source.readClass() as JClass;
    bool isConst = source.readBool();
    source.end(tag);
    return JContextField(name, BoxLocal(enclosingClass), isConst: isConst);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.contextField);
    sink.begin(tag);
    sink.writeString(name);
    sink.writeClass(enclosingClass!);
    sink.writeBool(isConst);
    sink.end(tag);
  }

  // TODO(johnniwinther): Remove these anomalies. Maybe by separating the
  // J-entities from the K-entities.
  @override
  bool get isInstanceMember => false;

  @override
  bool get isTopLevel => false;

  @override
  bool get isStatic => false;
}

class JClosureClass extends JClass {
  /// Tag used for identifying serialized [JClosureClass] objects in a
  /// debugging data stream.
  static const String tag = 'closure-class';

  JClosureClass(super.library, super.name) : super(isAbstract: false);

  factory JClosureClass.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    JLibrary library = source.readLibrary() as JLibrary;
    String name = source.readString();
    source.end(tag);
    return JClosureClass(library, name);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassKind.closure);
    sink.begin(tag);
    sink.writeLibrary(library);
    sink.writeString(name);
    sink.end(tag);
  }

  @override
  bool get isClosure => true;

  @override
  String toString() => '${jsElementPrefix}closure_class($name)';
}

class AnonymousClosureLocal implements Local {
  final JClosureClass closureClass;

  AnonymousClosureLocal(this.closureClass);

  @override
  String get name => '';

  @override
  int get hashCode => closureClass.hashCode * 13;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! AnonymousClosureLocal) return false;
    return closureClass == other.closureClass;
  }

  @override
  String toString() =>
      '${jsElementPrefix}anonymous_closure_local(${closureClass.name})';
}

class JClosureField extends JField implements PrivatelyNamedJSEntity {
  /// Tag used for identifying serialized [JClosureClass] objects in a
  /// debugging data stream.
  static const String tag = 'closure-field';

  @override
  final String declaredName;

  JClosureField(
    String name,
    JsClosureClassInfo containingClass,
    String declaredName, {
    required bool isConst,
    required bool isAssignable,
  }) : this.internal(
         containingClass.closureClassEntity.library,
         containingClass.closureClassEntity as JClosureClass,
         Name(name, containingClass.closureClassEntity.library.canonicalUri),
         declaredName,
         isAssignable: isAssignable,
         isConst: isConst,
       );

  JClosureField.internal(
    super.library,
    JClosureClass super.enclosingClass,
    super.memberName,
    this.declaredName, {
    required super.isConst,
    required super.isAssignable,
  }) : super(isStatic: false);

  factory JClosureField.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final cls = source.readClass() as JClosureClass;
    String name = source.readString();
    String declaredName = source.readString();
    bool isConst = source.readBool();
    bool isAssignable = source.readBool();
    source.end(tag);
    return JClosureField.internal(
      cls.library,
      cls,
      Name(name, cls.library.canonicalUri),
      declaredName,
      isAssignable: isAssignable,
      isConst: isConst,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.closureField);
    sink.begin(tag);
    sink.writeClass(enclosingClass!);
    sink.writeString(name);
    sink.writeString(declaredName);
    sink.writeBool(isConst);
    sink.writeBool(isAssignable);
    sink.end(tag);
  }

  @override
  Entity get rootOfScope => enclosingClass!;
}

class ContextClassData implements JClassData {
  /// Tag used for identifying serialized [ContextClassData] objects in a
  /// debugging data stream.
  static const String tag = 'context-class-data';

  @override
  final ClassDefinition definition;

  @override
  final InterfaceType? thisType;

  @override
  final OrderedTypeSet orderedTypeSet;

  @override
  final InterfaceType? supertype;

  ContextClassData(
    this.definition,
    this.thisType,
    this.supertype,
    this.orderedTypeSet,
  );

  factory ContextClassData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ClassDefinition definition = ClassDefinition.readFromDataSource(source);
    InterfaceType thisType = source.readDartType() as InterfaceType;
    InterfaceType supertype = source.readDartType() as InterfaceType;
    OrderedTypeSet orderedTypeSet = OrderedTypeSet.readFromDataSource(source);
    source.end(tag);
    return ContextClassData(definition, thisType, supertype, orderedTypeSet);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassDataKind.context);
    sink.begin(tag);
    definition.writeToDataSink(sink);
    sink.writeDartType(thisType!);
    sink.writeDartType(supertype!);
    orderedTypeSet.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  bool get isMixinApplication => false;

  @override
  bool get isEnumClass => false;

  @override
  FunctionType? get callType => null;

  @override
  List<InterfaceType> get interfaces => const <InterfaceType>[];

  @override
  InterfaceType? get mixedInType => null;

  @override
  InterfaceType? get jsInteropType => thisType;

  @override
  InterfaceType? get rawType => thisType;

  @override
  InterfaceType? get instantiationToBounds => thisType;

  @override
  List<Variance> getVariances() => [];
}

class ClosureClassData extends ContextClassData {
  /// Tag used for identifying serialized [ClosureClassData] objects in a
  /// debugging data stream.
  static const String tag = 'closure-class-data';

  @override
  FunctionType? callType;

  ClosureClassData(
    super.definition,
    super.thisType,
    super.supertype,
    super.orderedTypeSet,
  );

  factory ClosureClassData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ClassDefinition definition = ClassDefinition.readFromDataSource(source);
    InterfaceType thisType = source.readDartType() as InterfaceType;
    InterfaceType supertype = source.readDartType() as InterfaceType;
    OrderedTypeSet orderedTypeSet = OrderedTypeSet.readFromDataSource(source);
    FunctionType callType = source.readDartType() as FunctionType;
    source.end(tag);
    return ClosureClassData(definition, thisType, supertype, orderedTypeSet)
      ..callType = callType;
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassDataKind.closure);
    sink.begin(tag);
    definition.writeToDataSink(sink);
    sink.writeDartType(thisType!);
    sink.writeDartType(supertype!);
    orderedTypeSet.writeToDataSink(sink);
    sink.writeDartType(callType!);
    sink.end(tag);
  }
}

abstract class ClosureMemberData implements JMemberData {
  @override
  final MemberDefinition definition;
  final InterfaceType? memberThisType;

  ClosureMemberData(this.definition, this.memberThisType);

  @override
  InterfaceType? getMemberThisType(covariant JsToElementMap elementMap) {
    return memberThisType;
  }
}

class ClosureFunctionData extends ClosureMemberData
    with FunctionDataTypeVariablesMixin, FunctionDataForEachParameterMixin
    implements FunctionData {
  /// Tag used for identifying serialized [ClosureFunctionData] objects in a
  /// debugging data stream.
  static const String tag = 'closure-function-data';

  final FunctionType functionType;
  @override
  ir.FunctionNode get functionNode => _functionNode.loaded();
  final Deferrable<ir.FunctionNode> _functionNode;
  @override
  final ClassTypeVariableAccess classTypeVariableAccess;

  ClosureFunctionData(
    super.definition,
    super.memberThisType,
    this.functionType,
    ir.FunctionNode functionNode,
    this.classTypeVariableAccess,
  ) : _functionNode = Deferrable.eager(functionNode);

  ClosureFunctionData._deserialized(
    super.definition,
    super.memberThisType,
    this.functionType,
    this._functionNode,
    this.classTypeVariableAccess,
  );

  static ir.FunctionNode _readFunctionNode(DataSourceReader source) {
    return source.readTreeNode() as ir.FunctionNode;
  }

  factory ClosureFunctionData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ClosureMemberDefinition definition =
        MemberDefinition.readFromDataSource(source) as ClosureMemberDefinition;
    InterfaceType? memberThisType =
        source.readDartTypeOrNull() as InterfaceType?;
    FunctionType functionType = source.readDartType() as FunctionType;
    Deferrable<ir.FunctionNode> functionNode = source.readDeferrable(
      _readFunctionNode,
    );
    ClassTypeVariableAccess classTypeVariableAccess = source.readEnum(
      ClassTypeVariableAccess.values,
    );
    source.end(tag);
    return ClosureFunctionData._deserialized(
      definition,
      memberThisType,
      functionType,
      functionNode,
      classTypeVariableAccess,
    );
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.closureFunction);
    sink.begin(tag);
    definition.writeToDataSink(sink);
    sink.writeDartTypeOrNull(memberThisType);
    sink.writeDartType(functionType);
    sink.writeDeferrable(() => sink.writeTreeNode(functionNode));
    sink.writeEnum(classTypeVariableAccess);
    sink.end(tag);
  }

  @override
  FunctionType getFunctionType(IrToElementMap elementMap) {
    return functionType;
  }
}

class ClosureFieldData extends ClosureMemberData implements JFieldData {
  /// Tag used for identifying serialized [ClosureFieldData] objects in a
  /// debugging data stream.
  static const String tag = 'closure-field-data';

  DartType? _type;

  ClosureFieldData(super.definition, super.memberThisType);

  factory ClosureFieldData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    InterfaceType? memberThisType =
        source.readDartTypeOrNull() as InterfaceType?;
    source.end(tag);
    return ClosureFieldData(definition, memberThisType);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.closureField);
    sink.begin(tag);
    definition.writeToDataSink(sink);
    sink.writeDartTypeOrNull(memberThisType);
    sink.end(tag);
  }

  @override
  DartType getFieldType(IrToElementMap elementMap) {
    if (_type != null) return _type!;
    ir.Node sourceNode = definition.node;
    ir.DartType type;
    if (sourceNode is ir.Class) {
      type = sourceNode.getThisType(
        elementMap.coreTypes,
        sourceNode.enclosingLibrary.nonNullable,
      );
    } else if (sourceNode is ir.VariableDeclaration) {
      type = sourceNode.type;
    } else if (sourceNode is ir.Field) {
      type = sourceNode.type;
    } else if (sourceNode is ir.TypeLiteral) {
      type = sourceNode.type;
    } else if (sourceNode is ir.Typedef) {
      type = sourceNode.type!;
    } else if (sourceNode is ir.TypeParameter) {
      type = sourceNode.bound;
    } else {
      failedAt(
        definition.location,
        'Unexpected node type $sourceNode in '
        'ClosureFieldData.getFieldType',
      );
    }
    return _type = elementMap.getDartType(type);
  }

  @override
  bool get isCovariantByDeclaration => false;

  @override
  ClassTypeVariableAccess get classTypeVariableAccess =>
      ClassTypeVariableAccess.none;
}
