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

// @dart = 2.10

library js_backend.native_data;

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

import '../common.dart';
import '../common/elements.dart' show ElementEnvironment;
import '../elements/entities.dart';
import '../ir/annotations.dart';
import '../js_model/js_to_frontend_map.dart' show identity, JsToFrontendMap;
import '../kernel/element_map.dart';
import '../native/behavior.dart' show NativeBehavior;
import '../serialization/serialization_interfaces.dart';
import '../util/util.dart';

import 'native_data_interfaces.dart' as interfaces;

class NativeBasicDataBuilder {
  bool _closed = false;

  /// Tag info for native JavaScript classes names. See
  /// [setNativeClassTagInfo].
  final Map<ClassEntity, NativeClassTag> _nativeClassTagInfo = {};

  /// The JavaScript libraries implemented via typed JavaScript interop.
  final Map<LibraryEntity, String> _jsInteropLibraries = {};

  /// The JavaScript classes implemented via typed JavaScript interop.
  final Map<ClassEntity, String> _jsInteropClasses = {};

  /// JavaScript interop classes annotated with `@anonymous`
  final Set<ClassEntity> _anonymousJsInteropClasses = {};

  /// The JavaScript members implemented via typed JavaScript interop.
  final Map<MemberEntity, String> _jsInteropMembers = {};

  /// Sets the native tag info for [cls].
  ///
  /// The tag info string contains comma-separated 'words' which are either
  /// dispatch tags (having JavaScript identifier syntax) and directives that
  /// begin with `!`.
  void setNativeClassTagInfo(ClassEntity cls, String tagText) {
    assert(
        !_closed,
        failedAt(
            cls,
            "NativeBasicDataBuilder is closed. "
            "Trying to mark $cls as a native class."));

    // TODO(johnniwinther): Assert that this is only called once. The memory
    // compiler copies pre-processed elements into a new compiler through
    // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
    // method.
    assert(
        _nativeClassTagInfo[cls] == null ||
            _nativeClassTagInfo[cls].text == tagText,
        failedAt(
            cls,
            "Native tag info set inconsistently on $cls: "
            "Existing tag info '${_nativeClassTagInfo[cls]}', "
            "new tag info '$tagText'."));
    _nativeClassTagInfo[cls] = NativeClassTag(tagText);
  }

  /// Marks [element] as an explicit part of js interop.
  ///
  /// If [name] is provided, it sets the explicit js interop name for the
  /// library [element], other the js interop name is expected to be computed
  /// later.
  void markAsJsInteropLibrary(LibraryEntity element, {String name}) {
    assert(
        !_closed,
        failedAt(
            element,
            "NativeBasicDataBuilder is closed. "
            "Trying to mark $element as a js-interop library."));
    _jsInteropLibraries[element] = name;
  }

  /// Marks [element] as an explicit part of js interop.
  ///
  /// If [name] is provided, it sets the explicit js interop name for the
  /// class [element], other the js interop name is expected to be computed
  /// later.
  void markAsJsInteropClass(ClassEntity element,
      {String name, bool isAnonymous = false}) {
    assert(
        !_closed,
        failedAt(
            element,
            "NativeBasicDataBuilder is closed. "
            "Trying to mark $element as a js-interop class."));
    _jsInteropClasses[element] = name;
    if (isAnonymous) {
      _anonymousJsInteropClasses.add(element);
    }
  }

  /// Marks [element] as an explicit part of js interop and sets the explicit js
  /// interop [name] for the member [element].
  void markAsJsInteropMember(MemberEntity element, String name) {
    assert(
        !_closed,
        failedAt(
            element,
            "NativeBasicDataBuilder is closed. "
            "Trying to mark $element as a js-interop member."));
    _jsInteropMembers[element] = name;
  }

  /// Creates the [NativeBasicData] object for the data collected in this
  /// builder.
  NativeBasicData close(ElementEnvironment environment) {
    _closed = true;
    return NativeBasicData(
        environment,
        false,
        _nativeClassTagInfo,
        _jsInteropLibraries,
        _jsInteropClasses,
        _anonymousJsInteropClasses,
        _jsInteropMembers);
  }

  void reopenForTesting() {
    _closed = false;
  }
}

/// Basic information for native classes and js-interop libraries and classes.
///
/// This information is computed during loading using [NativeBasicDataBuilder].
class NativeBasicData implements interfaces.NativeBasicData {
  /// Tag used for identifying serialized [NativeBasicData] objects in a
  /// debugging data stream.
  static const String tag = 'native-basic-data';

  final ElementEnvironment _env;

  bool _isAllowInteropUsed;

  /// Tag info for native JavaScript classes names. See
  /// [setNativeClassTagInfo].
  final Map<ClassEntity, NativeClassTag> _nativeClassTagInfo;

  /// The JavaScript libraries implemented via typed JavaScript interop.
  final Map<LibraryEntity, String> _jsInteropLibraries;

  /// The JavaScript classes implemented via typed JavaScript interop.
  final Map<ClassEntity, String> _jsInteropClasses;

  /// JavaScript interop classes annotated with `@anonymous`
  final Set<ClassEntity> _anonymousJsInteropClasses;

  /// The JavaScript members implemented via typed JavaScript interop.
  final Map<MemberEntity, String> _jsInteropMembers;

  NativeBasicData(
      this._env,
      this._isAllowInteropUsed,
      this._nativeClassTagInfo,
      this._jsInteropLibraries,
      this._jsInteropClasses,
      this._anonymousJsInteropClasses,
      this._jsInteropMembers);

  factory NativeBasicData.fromIr(
      KernelToElementMap map, IrAnnotationData data) {
    ElementEnvironment env = map.elementEnvironment;
    Map<ClassEntity, NativeClassTag> nativeClassTagInfo = {};
    Map<LibraryEntity, String> jsInteropLibraries = {};
    Map<ClassEntity, String> jsInteropClasses = {};
    Set<ClassEntity> anonymousJsInteropClasses = {};
    Map<MemberEntity, String> jsInteropMembers = {};

    data.forEachNativeClass((ir.Class node, String text) {
      nativeClassTagInfo[map.getClass(node)] = NativeClassTag(text);
    });
    data.forEachJsInteropLibrary((ir.Library node, String name) {
      jsInteropLibraries[env.lookupLibrary(node.importUri, required: true)] =
          name;
    });
    data.forEachJsInteropClass((ir.Class node, String name,
        {bool isAnonymous}) {
      ClassEntity cls = map.getClass(node);
      jsInteropClasses[cls] = name;
      if (isAnonymous) {
        anonymousJsInteropClasses.add(cls);
      }
    });
    data.forEachJsInteropMember((ir.Member node, String name) {
      if (memberIsIgnorable(node)) return;
      jsInteropMembers[map.getMember(node)] = name;
    });

    return NativeBasicData(env, false, nativeClassTagInfo, jsInteropLibraries,
        jsInteropClasses, anonymousJsInteropClasses, jsInteropMembers);
  }

  /// Deserializes a [NativeBasicData] object from [source].
  factory NativeBasicData.readFromDataSource(
      DataSourceReader source, ElementEnvironment elementEnvironment) {
    source.begin(tag);
    bool isAllowInteropUsed = source.readBool();
    Map<ClassEntity, NativeClassTag> nativeClassTagInfo =
        source.readClassMap(() {
      List<String> names = source.readStrings() /*!*/;
      bool isNonLeaf = source.readBool();
      return NativeClassTag.internal(names, isNonLeaf);
    });
    Map<LibraryEntity, String> jsInteropLibraries =
        source.readLibraryMap(source.readString);
    Map<ClassEntity, String> jsInteropClasses =
        source.readClassMap(source.readString);
    Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
    Map<MemberEntity, String> jsInteropMembers =
        source.readMemberMap((MemberEntity member) => source.readString());
    source.end(tag);
    return NativeBasicData(
        elementEnvironment,
        isAllowInteropUsed,
        nativeClassTagInfo,
        jsInteropLibraries,
        jsInteropClasses,
        anonymousJsInteropClasses,
        jsInteropMembers);
  }

  /// Serializes this [NativeBasicData] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeBool(isAllowInteropUsed);
    sink.writeClassMap(_nativeClassTagInfo, (NativeClassTag tag) {
      sink.writeStrings(tag.names);
      sink.writeBool(tag.isNonLeaf);
    });
    sink.writeLibraryMap(_jsInteropLibraries, sink.writeString);
    sink.writeClassMap(_jsInteropClasses, sink.writeString);
    sink.writeClasses(_anonymousJsInteropClasses);
    sink.writeMemberMap(_jsInteropMembers,
        (MemberEntity member, String name) => sink.writeString(name));
    sink.end(tag);
  }

  /// Returns `true` if `allowInterop()` is invoked.
  bool get isAllowInteropUsed => _isAllowInteropUsed;

  /// Marks `allowInterop()` as used.
  ///
  /// [isAllowInteropUsed] is initially false on the closed world, and is only
  /// set during codegen enqueuing.
  void registerAllowInterop() {
    _isAllowInteropUsed = true;
  }

  /// Returns `true` if [cls] corresponds to a native JavaScript class.
  ///
  /// A class is marked as native either through the `@Native(...)` annotation
  /// allowed for internal libraries or via the typed JavaScriptInterop
  /// mechanism allowed for user libraries.
  @override
  bool isNativeClass(ClassEntity element) {
    if (isJsInteropClass(element)) return true;
    return _nativeClassTagInfo.containsKey(element);
  }

  /// Returns the list of non-directive native tag words for [cls].
  @override
  List<String> getNativeTagsOfClass(ClassEntity cls) {
    return _nativeClassTagInfo[cls].names;
  }

  /// Returns `true` if [cls] has a `!nonleaf` tag word.
  bool hasNativeTagsForcedNonLeaf(ClassEntity cls) {
    return _nativeClassTagInfo[cls].isNonLeaf;
  }

  /// Returns `true` if js interop features are used.
  bool get isJsInteropUsed =>
      _jsInteropLibraries.isNotEmpty || _jsInteropClasses.isNotEmpty;

  /// Returns `true` if [element] is a JsInterop library.
  bool isJsInteropLibrary(LibraryEntity element) {
    return _jsInteropLibraries.containsKey(element);
  }

  /// Returns `true` if [element] is a JsInterop class.
  @override
  bool isJsInteropClass(ClassEntity element) {
    return _jsInteropClasses.containsKey(element);
  }

  /// Returns `true` if [element] is explicitly marked as part of JsInterop.
  bool _isJsInteropMember(MemberEntity element) {
    return _jsInteropMembers.containsKey(element);
  }

  /// Returns `true` if [element] is a JsInterop member.
  bool isJsInteropMember(MemberEntity element) {
    // TODO(johnniwinther): Share this with [NativeData.isJsInteropMember].
    if (element.isFunction ||
        element.isConstructor ||
        element.isGetter ||
        element.isSetter) {
      FunctionEntity function = element;
      if (!function.isExternal) return false;

      if (_isJsInteropMember(function)) return true;
      if (function.enclosingClass != null) {
        return isJsInteropClass(function.enclosingClass);
      }
      if (function.isTopLevel) {
        return isJsInteropLibrary(function.library);
      }
      return false;
    } else {
      return _isJsInteropMember(element);
    }
  }

  /// Returns `true` if [element] or any of its superclasses is native.
  bool isNativeOrExtendsNative(ClassEntity element) {
    if (element == null) return false;
    if (isNativeClass(element) || isJsInteropClass(element)) {
      return true;
    }
    return isNativeOrExtendsNative(_env.getSuperClass(element));
  }

  NativeBasicData convert(JsToFrontendMap map, ElementEnvironment environment) {
    Map<ClassEntity, NativeClassTag> nativeClassTagInfo =
        <ClassEntity, NativeClassTag>{};
    _nativeClassTagInfo.forEach((ClassEntity cls, NativeClassTag tag) {
      nativeClassTagInfo[map.toBackendClass(cls)] = tag;
    });
    Map<LibraryEntity, String> jsInteropLibraries =
        map.toBackendLibraryMap(_jsInteropLibraries, identity);
    Map<ClassEntity, String> jsInteropClasses =
        map.toBackendClassMap(_jsInteropClasses, identity);
    Set<ClassEntity> anonymousJsInteropClasses =
        map.toBackendClassSet(_anonymousJsInteropClasses);
    Map<MemberEntity, String> jsInteropMembers =
        map.toBackendMemberMap(_jsInteropMembers, identity);
    return NativeBasicData(
        environment,
        isAllowInteropUsed,
        nativeClassTagInfo,
        jsInteropLibraries,
        jsInteropClasses,
        anonymousJsInteropClasses,
        jsInteropMembers);
  }
}

class NativeDataBuilder {
  final NativeBasicData _nativeBasicData;

  /// The JavaScript names for native JavaScript elements implemented.
  final Map<MemberEntity, String> _nativeMemberName = {};

  /// Cache for [NativeBehavior]s for calling native methods.
  final Map<FunctionEntity, NativeBehavior> _nativeMethodBehavior = {};

  /// Cache for [NativeBehavior]s for reading from native fields.
  final Map<MemberEntity, NativeBehavior> _nativeFieldLoadBehavior = {};

  /// Cache for [NativeBehavior]s for writing to native fields.
  final Map<MemberEntity, NativeBehavior> _nativeFieldStoreBehavior = {};

  NativeDataBuilder(this._nativeBasicData);

  /// Sets the native [name] for the member [element].
  ///
  /// This name is used for [element] in the generated JavaScript.
  void setNativeMemberName(MemberEntity element, String name) {
    // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
    // might enqueue [element] several times (before processing it) and computes
    // name on each call to `internalAddToWorkList`.
    assert(
        _nativeMemberName[element] == null ||
            _nativeMemberName[element] == name,
        failedAt(
            element,
            "Native member name set inconsistently on $element: "
            "Existing name '${_nativeMemberName[element]}', "
            "new name '$name'."));
    _nativeMemberName[element] = name;
  }

  /// Registers the [behavior] for calling the native [method].
  void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) {
    _nativeMethodBehavior[method] = behavior;
  }

  /// Registers the [behavior] for reading from the native [field].
  void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) {
    _nativeFieldLoadBehavior[field] = behavior;
  }

  /// Registers the [behavior] for writing to the native [field].
  void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) {
    _nativeFieldStoreBehavior[field] = behavior;
  }

  /// Closes this builder and creates the resulting [NativeData] object.
  NativeData close() => NativeData(
      _nativeBasicData,
      _nativeMemberName,
      _nativeMethodBehavior,
      _nativeFieldLoadBehavior,
      _nativeFieldStoreBehavior);
}

/// Additional element information for native classes and methods and js-interop
/// methods.
///
/// This information is computed during resolution using [NativeDataBuilder].
// TODO(johnniwinther): Remove fields that overlap with [NativeBasicData], like
// [anonymousJsInteropClasses].
class NativeData implements NativeBasicData {
  /// Tag used for identifying serialized [NativeData] objects in a
  /// debugging data stream.
  static const String tag = 'native-data';

  /// Prefix used to escape JS names that are not valid Dart names
  /// when using JSInterop.
  static const String _jsInteropEscapePrefix = r'JS$';

  final NativeBasicData _nativeBasicData;

  /// The JavaScript names for native JavaScript elements implemented.
  final Map<MemberEntity, String> _nativeMemberName;

  /// Cache for [NativeBehavior]s for calling native methods.
  final Map<FunctionEntity, NativeBehavior> _nativeMethodBehavior;

  /// Cache for [NativeBehavior]s for reading from native fields.
  final Map<MemberEntity, NativeBehavior> _nativeFieldLoadBehavior;

  /// Cache for [NativeBehavior]s for writing to native fields.
  final Map<MemberEntity, NativeBehavior> _nativeFieldStoreBehavior;

  NativeData(
      this._nativeBasicData,
      this._nativeMemberName,
      this._nativeMethodBehavior,
      this._nativeFieldLoadBehavior,
      this._nativeFieldStoreBehavior);

  factory NativeData.fromIr(KernelToElementMap map, IrAnnotationData data) {
    NativeBasicData nativeBasicData = NativeBasicData.fromIr(map, data);
    Map<MemberEntity, String> nativeMemberName = {};
    Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = {};
    Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = {};
    Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = {};

    data.forEachNativeMethodData((ir.Member node,
        String name,
        Iterable<String> createsAnnotations,
        Iterable<String> returnsAnnotations) {
      MemberEntity member = map.getMember(node);
      nativeMemberName[member] = name;
      bool isJsInterop = nativeBasicData.isJsInteropMember(member);
      nativeMethodBehavior[member] = map.getNativeBehaviorForMethod(
          node, createsAnnotations, returnsAnnotations,
          isJsInterop: isJsInterop);
    });

    data.forEachNativeFieldData((ir.Member node,
        String name,
        Iterable<String> createsAnnotations,
        Iterable<String> returnsAnnotations) {
      FieldEntity field = map.getMember(node);
      nativeMemberName[field] = name;
      bool isJsInterop = nativeBasicData.isJsInteropMember(field);
      nativeFieldLoadBehavior[field] = map.getNativeBehaviorForFieldLoad(
          node, createsAnnotations, returnsAnnotations,
          isJsInterop: isJsInterop);
      nativeFieldStoreBehavior[field] =
          map.getNativeBehaviorForFieldStore(node);
    });

    return NativeData(nativeBasicData, nativeMemberName, nativeMethodBehavior,
        nativeFieldLoadBehavior, nativeFieldStoreBehavior);
  }

  /// Deserializes a [NativeData] object from [source].
  factory NativeData.readFromDataSource(
      DataSourceReader source, ElementEnvironment elementEnvironment) {
    source.begin(tag);
    NativeBasicData nativeBasicData =
        NativeBasicData.readFromDataSource(source, elementEnvironment);
    Map<MemberEntity, String> nativeMemberName =
        source.readMemberMap((MemberEntity member) => source.readString());
    Map<FunctionEntity, NativeBehavior> nativeMethodBehavior =
        source.readMemberMap(
            (MemberEntity member) => NativeBehavior.readFromDataSource(source));
    Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
        source.readMemberMap(
            (MemberEntity member) => NativeBehavior.readFromDataSource(source));
    Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
        source.readMemberMap(
            (MemberEntity member) => NativeBehavior.readFromDataSource(source));
    source.end(tag);
    return NativeData(nativeBasicData, nativeMemberName, nativeMethodBehavior,
        nativeFieldLoadBehavior, nativeFieldStoreBehavior);
  }

  /// Serializes this [NativeData] to [sink].
  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    _nativeBasicData.writeToDataSink(sink);

    sink.writeMemberMap(_nativeMemberName,
        (MemberEntity member, String name) => sink.writeString(name));

    sink.writeMemberMap(_nativeMethodBehavior,
        (MemberEntity member, NativeBehavior behavior) {
      behavior.writeToDataSink(sink);
    });

    sink.writeMemberMap(_nativeFieldLoadBehavior,
        (MemberEntity member, NativeBehavior behavior) {
      behavior.writeToDataSink(sink);
    });
    sink.writeMemberMap(_nativeFieldStoreBehavior,
        (MemberEntity member, NativeBehavior behavior) {
      behavior.writeToDataSink(sink);
    });

    sink.end(tag);
  }

  @override
  bool get _isAllowInteropUsed => _nativeBasicData._isAllowInteropUsed;

  @override
  set _isAllowInteropUsed(bool value) =>
      _nativeBasicData._isAllowInteropUsed = value;

  @override
  bool get isAllowInteropUsed => _nativeBasicData.isAllowInteropUsed;

  @override
  void registerAllowInterop() => _nativeBasicData.registerAllowInterop();

  @override
  Map<LibraryEntity, String> get _jsInteropLibraries =>
      _nativeBasicData._jsInteropLibraries;

  @override
  Set<ClassEntity> get _anonymousJsInteropClasses =>
      _nativeBasicData._anonymousJsInteropClasses;

  @override
  Map<ClassEntity, String> get _jsInteropClasses =>
      _nativeBasicData._jsInteropClasses;

  @override
  Map<MemberEntity, String> get _jsInteropMembers =>
      _nativeBasicData._jsInteropMembers;

  /// Returns `true` if [element] has an `@Anonymous` annotation.
  bool isAnonymousJsInteropClass(ClassEntity element) {
    return _anonymousJsInteropClasses.contains(element);
  }

  @override
  bool isNativeClass(ClassEntity element) =>
      _nativeBasicData.isNativeClass(element);

  @override
  List<String> getNativeTagsOfClass(ClassEntity cls) =>
      _nativeBasicData.getNativeTagsOfClass(cls);

  @override
  bool hasNativeTagsForcedNonLeaf(ClassEntity cls) =>
      _nativeBasicData.hasNativeTagsForcedNonLeaf(cls);

  @override
  bool get isJsInteropUsed => _nativeBasicData.isJsInteropUsed;

  @override
  bool isJsInteropLibrary(LibraryEntity element) =>
      _nativeBasicData.isJsInteropLibrary(element);

  @override
  bool isJsInteropClass(ClassEntity element) =>
      _nativeBasicData.isJsInteropClass(element);

  @override
  bool isNativeOrExtendsNative(ClassEntity element) =>
      _nativeBasicData.isNativeOrExtendsNative(element);

  /// Returns the explicit js interop name for library [element].
  String getJsInteropLibraryName(LibraryEntity element) {
    return _jsInteropLibraries[element];
  }

  /// Returns the explicit js interop name for class [element].
  String getJsInteropClassName(ClassEntity element) {
    return _jsInteropClasses[element];
  }

  /// Returns the explicit js interop name for member [element].
  String getJsInteropMemberName(MemberEntity element) {
    return _jsInteropMembers[element];
  }

  @override
  bool _isJsInteropMember(MemberEntity element) {
    return _jsInteropMembers.containsKey(element);
  }

  @override
  bool isJsInteropMember(MemberEntity element) {
    if (element.isFunction ||
        element.isConstructor ||
        element.isGetter ||
        element.isSetter) {
      FunctionEntity function = element;
      if (!function.isExternal) return false;

      if (_isJsInteropMember(function)) return true;
      if (function.enclosingClass != null) {
        return isJsInteropClass(function.enclosingClass);
      }
      if (function.isTopLevel) {
        return isJsInteropLibrary(function.library);
      }
      return false;
    } else {
      return _isJsInteropMember(element);
    }
  }

  /// Returns `true` if the name of [element] is fixed for the generated
  /// JavaScript.
  bool hasFixedBackendName(MemberEntity element) {
    return isJsInteropMember(element) || _nativeMemberName.containsKey(element);
  }

  /// Computes the name for [element] to use in the generated JavaScript. This
  /// is either given through a native annotation or a js interop annotation.
  String getFixedBackendName(MemberEntity element) {
    String name = _nativeMemberName[element];
    if (name == null && isJsInteropMember(element)) {
      if (element.isConstructor) {
        name = _jsClassNameHelper(element.enclosingClass);
      } else {
        name = _jsMemberNameHelper(element);
        // Top-level static JS interop members can be associated with a dotted
        // name, if so, fixedBackendName is the last segment.
        if (element.isTopLevel && name.contains('.')) {
          name = name.substring(name.lastIndexOf('.') + 1);
        }
      }
      _nativeMemberName[element] = name;
    }
    return name;
  }

  String _jsLibraryNameHelper(LibraryEntity element) {
    String jsInteropName = getJsInteropLibraryName(element);
    if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
    return 'self';
  }

  String _jsClassNameHelper(ClassEntity element) {
    String jsInteropName = getJsInteropClassName(element);
    if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
    return computeUnescapedJSInteropName(element.name);
  }

  String _jsMemberNameHelper(MemberEntity element) {
    String jsInteropName = _jsInteropMembers[element];
    assert(
        !(_jsInteropMembers.containsKey(element) && jsInteropName == null),
        failedAt(
            element,
            'Member $element is js interop but js interop name has not yet '
            'been computed.'));
    if (jsInteropName != null && jsInteropName.isNotEmpty) {
      return jsInteropName;
    }
    return computeUnescapedJSInteropName(element.name);
  }

  /// Returns a JavaScript path specifying the context in which
  /// [element.fixedBackendName] should be evaluated. Only applicable for
  /// elements using typed JavaScript interop.
  /// For example: fixedBackendPath for the static method createMap in the
  /// Map class of the goog.map JavaScript library would have path
  /// "goog.maps.Map".
  String getFixedBackendMethodPath(FunctionEntity element) {
    if (!isJsInteropMember(element)) return null;
    if (element.isInstanceMember) return 'this';
    if (element.isConstructor) {
      return _fixedBackendClassPath(element.enclosingClass);
    }
    StringBuffer sb = StringBuffer();
    sb.write(_jsLibraryNameHelper(element.library));
    if (element.enclosingClass != null) {
      sb
        ..write('.')
        ..write(_jsClassNameHelper(element.enclosingClass));
    }

    // Top-level static JS interop members can be associated with a dotted
    // name, if so, fixedBackendPath includes all but the last segment.
    final name = _jsMemberNameHelper(element);
    if (element.isTopLevel && name.contains('.')) {
      sb
        ..write('.')
        ..write(name.substring(0, name.lastIndexOf('.')));
    }
    return sb.toString();
  }

  String _fixedBackendClassPath(ClassEntity element) {
    if (!isJsInteropClass(element)) return null;
    return _jsLibraryNameHelper(element.library);
  }

  /// Returns `true` if [element] corresponds to a native JavaScript member.
  ///
  /// A member is marked as native either through the native mechanism
  /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal
  /// libraries or via the typed JavaScriptInterop mechanism allowed for user
  /// libraries.
  bool isNativeMember(MemberEntity element) {
    if (isJsInteropMember(element)) return true;
    return _nativeMemberName.containsKey(element);
  }

  /// Returns the [NativeBehavior] for calling the native [method].
  NativeBehavior getNativeMethodBehavior(FunctionEntity method) {
    assert(
        _nativeMethodBehavior.containsKey(method),
        failedAt(method,
            "No native method behavior has been computed for $method."));
    return _nativeMethodBehavior[method];
  }

  /// Returns the [NativeBehavior] for reading from the native [field].
  NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) {
    assert(
        _nativeFieldLoadBehavior.containsKey(field),
        failedAt(
            field,
            "No native field load behavior has been "
            "computed for $field."));
    return _nativeFieldLoadBehavior[field];
  }

  /// Returns the [NativeBehavior] for writing to the native [field].
  NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) {
    assert(
        _nativeFieldStoreBehavior.containsKey(field),
        failedAt(field,
            "No native field store behavior has been computed for $field."));
    return _nativeFieldStoreBehavior[field];
  }

  /// Apply JS$ escaping scheme to convert possible escaped Dart names into
  /// JS names.
  String computeUnescapedJSInteropName(String name) {
    return name.startsWith(_jsInteropEscapePrefix)
        ? name.substring(_jsInteropEscapePrefix.length)
        : name;
  }

  @override
  Map<ClassEntity, NativeClassTag> get _nativeClassTagInfo =>
      _nativeBasicData._nativeClassTagInfo;

  @override
  ElementEnvironment get _env => _nativeBasicData._env;

  @override
  NativeData convert(JsToFrontendMap map, ElementEnvironment environment) {
    NativeBasicData nativeBasicData =
        _nativeBasicData.convert(map, environment);
    Map<MemberEntity, String> nativeMemberName =
        map.toBackendMemberMap(_nativeMemberName, identity);
    final nativeMethodBehavior = <FunctionEntity, NativeBehavior>{};
    _nativeMethodBehavior
        .forEach((FunctionEntity method, NativeBehavior behavior) {
      FunctionEntity backendMethod = map.toBackendMember(method);
      if (backendMethod != null) {
        // If [method] isn't used it doesn't have a corresponding backend
        // method.
        nativeMethodBehavior[backendMethod] = behavior.convert(map);
      }
    });
    NativeBehavior _convertNativeBehavior(NativeBehavior behavior) =>
        behavior.convert(map);
    Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = map
        .toBackendMemberMap(_nativeFieldLoadBehavior, _convertNativeBehavior);
    Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = map
        .toBackendMemberMap(_nativeFieldStoreBehavior, _convertNativeBehavior);
    return NativeData(nativeBasicData, nativeMemberName, nativeMethodBehavior,
        nativeFieldLoadBehavior, nativeFieldStoreBehavior);
  }
}

class NativeClassTag {
  final List<String> names;
  final bool isNonLeaf;

  factory NativeClassTag(String tagText) {
    List<String> tags = tagText.split(',');
    List<String> names = tags.where((s) => !s.startsWith('!')).toList();
    bool isNonLeaf = tags.contains('!nonleaf');
    return NativeClassTag.internal(names, isNonLeaf);
  }

  NativeClassTag.internal(this.names, this.isNonLeaf);

  String get text {
    StringBuffer sb = StringBuffer();
    sb.write(names.join(','));
    if (isNonLeaf) {
      if (names.isNotEmpty) {
        sb.write(',');
      }
      sb.write('!nonleaf');
    }
    return sb.toString();
  }

  @override
  int get hashCode => Hashing.listHash(names, isNonLeaf.hashCode);

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! NativeClassTag) return false;
    return equalElements(names, other.names) && isNonLeaf == other.isNonLeaf;
  }

  @override
  String toString() => text;
}
