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

part of js_backend.namer;

/// Assigns JavaScript identifiers to Dart variables, class-names and members.
class MinifyNamer extends Namer
    with
        _MinifiedFieldNamer,
        _MinifyConstructorBodyNamer,
        _MinifiedOneShotInterceptorNamer {
  MinifyNamer(JClosedWorld closedWorld, FixedNames fixedNames)
      : super(closedWorld, fixedNames) {
    reserveBackendNames();
    fieldRegistry = _FieldNamingRegistry(this);
  }

  @override
  _FieldNamingRegistry fieldRegistry;

  @override
  String get genericInstantiationPrefix => r'$I';

  final ALPHABET_CHARACTERS = 52; // a-zA-Z.
  final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9.

  /// You can pass an invalid identifier to this and unlike its non-minifying
  /// counterpart it will never return the proposedName as the new fresh name.
  ///
  /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the
  /// minified names will always avoid clashing with annotated names or natives.
  @override
  String _generateFreshStringForName(String proposedName, NamingScope scope,
      {bool sanitizeForNatives = false, bool sanitizeForAnnotations = false}) {
    String freshName;
    String suggestion = scope.suggestName(proposedName);
    if (suggestion != null && scope.isUnused(suggestion)) {
      freshName = suggestion;
    } else {
      freshName = _getUnusedName(proposedName, scope);
    }
    scope.registerUse(freshName);
    return freshName;
  }

  /// Property names that are used on 'native' JavaScript classes.
  ///
  /// It is best not to use these names for dynamic call selectors.
  ///
  /// Dynamic calls to selectors that are used on an intercepted (e.g. String)
  /// class (e.g. String) or native class (e.g. HtmlElement) are not a problem
  /// since they are handled via the interceptor calling mechanism. Other
  /// selectors are called directly, so the minified selector should not be a
  /// name that accidentally collides with a JavaScript method.  For example,
  /// the minified call site for the dynamic call `item.yowza()` should not be
  /// `x.at()`, since, if `x` was a String, that would call
  /// `String.prototype.at` instead of generating an error.
  ///
  /// These names are reserved for the property names of fields, since fields
  /// are always accessed from a know receiver. (A 'field' of an unknown
  /// receiver would actually be the getter method.)
  ///
  /// These names could be used for selectors that use the interceptor calling
  /// convention, or for selectors are not called from a `dynamic` call site, or
  /// any other use where the JavaScript receiver is constrained to be something
  /// from within the dart program.
  ///
  /// TODO(7554): Refresh periodically.
  static const List<String> _reservedNativeProperties = [
    // 1 character
    'a', 'b', 'c', 'd', 'e', 'f', 'r', 'w', 'x', 'y', 'z', 'Q',

    // 2 characters
    'as', 'at', 'ax', 'ay', 'ch', 'CW', 'cx', 'cy', 'db', 'dx', 'dy', 'fr',
    'fx', 'fy', 'go', 'id', 'k1', 'k2', 'k3', 'k4', 'ok', 'p1', 'p2', 'p3',
    'p4', 'R8', 'RG', 'rx', 'ry', 'to', 'x1', 'x2', 'xr', 'y1', 'y2',

    // 3 characters
    'add', 'all', 'alt', 'arc', 'big', 'CCW', 'cmp', 'csp', 'dir', 'div', 'end',
    'eye', 'get', 'has', 'hid', 'in1', 'in2', 'ink', 'INT', 'key', 'low', 'm11',
    'm12', 'm13', 'm14', 'm21', 'm22', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34',
    'm41', 'm42', 'm43', 'm44', 'map', 'max', 'MAX', 'mid', 'min', 'MIN', 'mul',
    'now', 'ONE', 'pad', 'pan', 'pop', 'put', 'R8I', 'RED', 'rel', 'rev', 'RG8',
    'RGB', 'rtt', 'sdp', 'set', 'src', 'sub', 'sup', 'tag', 'tee', 'top', 'upX',
    'upY', 'upZ', 'url', 'URL', 'usb',

    // 4 characters
    'abbr', 'axes', 'axis', 'back', 'BACK', 'beta', 'bias', 'bind', 'blob',
    'blur', 'body', 'bold', 'BOOL', 'BYTE', 'call', 'cite', 'city', 'clip',
    'code', 'cols', 'cues', 'data', 'DECR', 'DONE', 'dtmf', 'exec', 'face',
    'fill', 'find', 'flat', 'font', 'form', 'gain', 'hash', 'head', 'hide',
    'high', 'hint', 'host', 'href', 'icon', 'INCR', 'is2D', 'item', 'join',
    'json', 'KEEP', 'keys', 'kind', 'knee', 'lang', 'left', 'LESS', 'line',
    'link', 'list', 'load', 'lock', 'loop', 'mark', 'mode', 'name', 'node',
    'NONE', 'open', 'OPEN', 'part', 'path', 'ping', 'play', 'port', 'push',
    'R16F', 'R16I', 'R32F', 'R32I', 'R8UI', 'rate', 'read', 'rect', 'refX',
    'refY', 'RG8I', 'RGB8', 'RGBA', 'role', 'root', 'rows', 'save', 'sctp',
    'seed', 'seek', 'send', 'show', 'sign', 'size', 'slot', 'some', 'sort',
    'span', 'SRGB', 'step', 'stop', 'sync', 'test', 'text', 'then', 'time',
    'tone', 'trim', 'type', 'unit', 'view', 'wrap', 'ZERO',
  ];

  void reserveBackendNames() {
    for (String name in _reservedNativeProperties) {
      if (name.length < 2) {
        // Ensure the 1-letter names are disambiguated to the same name.
        String disambiguatedName = name;
        reservePublicMemberName(name, disambiguatedName);
      }
      instanceScope.registerUse(name);
      // Getter and setter names are autogenerated by prepending 'g' and 's' to
      // field names.  Therefore there are some field names we don't want to
      // use.  It is implicit in the next line that the banned prefix is
      // only one character.
      if (_hasBannedPrefix(name)) {
        instanceScope.registerUse(name.substring(1));
      }
    }

    // These popular names are present in most programs and deserve
    // single character minified names.  We could determine the popular names
    // individually per program, but that would mean that the output of the
    // minifier was less stable from version to version of the program being
    // minified.
    _populateSuggestedNames(instanceScope, const [
      r'$add',
      r'add$1',
      r'$and',
      r'$or',
      r'current',
      r'$shr',
      r'$eq',
      r'$ne',
      r'$index',
      r'$indexSet',
      r'$xor',
      r'clone$0',
      r'iterator',
      r'length',
      r'$lt',
      r'$gt',
      r'$le',
      r'$ge',
      r'moveNext$0',
      r'node',
      r'on',
      r'$negate',
      r'push',
      r'self',
      r'start',
      r'target',
      r'$shl',
      r'value',
      r'width',
      r'style',
      r'noSuchMethod$1',
      r'$mul',
      r'$div',
      r'$sub',
      r'$not',
      r'$mod',
      r'$tdiv',
      r'toString$0'
    ]);

    _populateSuggestedNames(globalScope, const [
      r'Object',
      'wrapException',
      r'$eq',
      r'S',
      r'ioore',
      r'UnsupportedError$',
      r'length',
      r'$sub',
      r'$add',
      r'$gt',
      r'$ge',
      r'$lt',
      r'$le',
      r'add',
      r'iae',
      r'ArgumentError$',
      r'BoundClosure',
      r'Closure',
      r'StateError$',
      r'getInterceptor$',
      r'max',
      r'$mul',
      r'Map',
      r'Key_Key',
      r'$div',
      r'List_List$from',
      r'LinkedHashMap_LinkedHashMap$_empty',
      r'LinkedHashMap_LinkedHashMap$_literal',
      r'min',
      r'RangeError$value',
      r'JSString',
      r'JSNumber',
      r'JSArray',
      r'createInvocationMirror',
      r'String',
      r'setArrayType',
      r'createRuntimeType'
    ]);
  }

  void _populateSuggestedNames(NamingScope scope, List<String> suggestions) {
    int c = $a - 1;
    String letter;
    for (String name in suggestions) {
      do {
        assert(c != $Z);
        c = (c == $z) ? $A : c + 1;
        letter = String.fromCharCodes([c]);
      } while (_hasBannedPrefix(letter) || scope.isUsed(letter));
      assert(!scope.hasSuggestion(name));
      scope.addSuggestion(name, letter);
    }
  }

  // This gets a minified name based on a hash of the proposed name.  This
  // is slightly less efficient than just getting the next name in a series,
  // but it means that small changes in the input program will give smallish
  // changes in the output, which can be useful for diffing etc.
  String _getUnusedName(String proposedName, NamingScope scope) {
    int hash = _calculateHash(proposedName);
    // Avoid very small hashes that won't try many names.
    hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime.

    // Try other n-character names based on the hash.  We try one to three
    // character identifiers.  For each length we try around 10 different names
    // in a predictable order determined by the proposed name.  This is in order
    // to make the renamer stable: small changes in the input should nornally
    // result in relatively small changes in the output.
    for (int n = 1; n <= 3; n++) {
      int h = hash;
      while (h > 10) {
        List<int> codes = [_letterNumber(h)];
        int h2 = h ~/ ALPHABET_CHARACTERS;
        for (int i = 1; i < n; i++) {
          codes.add(_alphaNumericNumber(h2));
          h2 ~/= ALPHANUMERIC_CHARACTERS;
        }
        final candidate = String.fromCharCodes(codes);
        if (scope.isUnused(candidate) &&
            !jsReserved.contains(candidate) &&
            !_hasBannedPrefix(candidate) &&
            (n != 1 || scope.isSuggestion(candidate))) {
          return candidate;
        }
        // Try again with a slightly different hash.  After around 10 turns
        // around this loop h is zero and we try a longer name.
        h ~/= 7;
      }
    }
    return _badName(hash, scope);
  }

  /// Instance members starting with g and s are reserved for getters and
  /// setters.
  static bool _hasBannedPrefix(String name) {
    int code = name.codeUnitAt(0);
    return code == $g || code == $s;
  }

  int _calculateHash(String name) {
    int h = 0;
    for (int i = 0; i < name.length; i++) {
      h += name.codeUnitAt(i);
      h &= 0xffffffff;
      h += h << 10;
      h &= 0xffffffff;
      h ^= h >> 6;
      h &= 0xffffffff;
    }
    return h;
  }

  /// Remember bad hashes to avoid using a the same character with long numbers
  /// for frequent hashes. For example, `closure` is a very common name.
  final Map<int, int> _badNames = {};

  /// If we can't find a hash based name in the three-letter space, then base
  /// the name on a letter and a counter.
  String _badName(int hash, NamingScope scope) {
    int count = _badNames.putIfAbsent(hash, () => 0);
    String startLetter = String.fromCharCodes([_letterNumber(hash + count)]);
    _badNames[hash] = count + 1;
    String name;
    int i = 0;
    do {
      name = "$startLetter${i++}";
    } while (scope.isUsed(name));
    // We don't need to check for banned prefix because the name is in the form
    // xnnn, where nnn is a number.  There can be no getter or setter called
    // gnnn since that would imply a numeric field name.
    return name;
  }

  int _letterNumber(int x) {
    if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS;
    if (x < 26) return $a + x;
    return $A + x - 26;
  }

  int _alphaNumericNumber(int x) {
    if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS;
    if (x < 26) return $a + x;
    if (x < 52) return $A + x - 26;
    return $0 + x - 52;
  }

  @override
  jsAst.Name instanceFieldPropertyName(FieldEntity element) {
    jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element);
    if (proposed != null) {
      return proposed;
    }
    return super.instanceFieldPropertyName(element);
  }
}

/// Implements naming for constructor bodies.
///
/// Constructor bodies are only called in settings where the target is
/// statically known. Therefore, we can share their names between classes.
/// However, to support calling the constructor body of a super constructor,
/// each level in the inheritance tree has to use its own names.
///
/// This class implements a naming scheme by counting the distance from
/// a given constructor to [Object], where distance is the number of
/// constructors declared along the inheritance chain.
class _ConstructorBodyNamingScope {
  final int _startIndex;
  final List<ConstructorEntity> _constructors;
  int get numberOfConstructors => _constructors.length;

  _ConstructorBodyNamingScope.rootScope(
      ClassEntity cls, ElementEnvironment environment)
      : _startIndex = 0,
        _constructors = _getConstructorList(cls, environment);

  _ConstructorBodyNamingScope.forClass(ClassEntity cls,
      _ConstructorBodyNamingScope superScope, ElementEnvironment environment)
      : _startIndex = superScope._startIndex + superScope.numberOfConstructors,
        _constructors = _getConstructorList(cls, environment);

  // Mixin Applications have constructors but we never generate code for them,
  // so they do not count in the inheritance chain.
  _ConstructorBodyNamingScope.forMixinApplication(
      ClassEntity cls, _ConstructorBodyNamingScope superScope)
      : _startIndex = superScope._startIndex + superScope.numberOfConstructors,
        _constructors = const [];

  factory _ConstructorBodyNamingScope(
      ClassEntity cls,
      Map<ClassEntity, _ConstructorBodyNamingScope> registry,
      ElementEnvironment environment) {
    return registry.putIfAbsent(cls, () {
      ClassEntity superclass = environment.getSuperClass(cls);
      if (superclass == null) {
        return _ConstructorBodyNamingScope.rootScope(cls, environment);
      } else if (environment.isMixinApplication(cls)) {
        return _ConstructorBodyNamingScope.forMixinApplication(cls,
            _ConstructorBodyNamingScope(superclass, registry, environment));
      } else {
        return _ConstructorBodyNamingScope.forClass(
            cls,
            _ConstructorBodyNamingScope(superclass, registry, environment),
            environment);
      }
    });
  }

  String constructorBodyKeyFor(ConstructorBodyEntity body) {
    int position = _constructors.indexOf(body.constructor);
    assert(position >= 0, failedAt(body, "constructor body missing"));
    return "@constructorBody@${_startIndex + position}";
  }

  static List<ConstructorEntity> _getConstructorList(
      ClassEntity cls, ElementEnvironment environment) {
    var result = <ConstructorEntity>[];
    environment.forEachConstructor(cls, result.add);
    return result;
  }
}

abstract class _MinifyConstructorBodyNamer implements Namer {
  final Map<ClassEntity, _ConstructorBodyNamingScope> _constructorBodyScopes =
      {};

  @override
  jsAst.Name constructorBodyName(ConstructorBodyEntity method) {
    _ConstructorBodyNamingScope scope = _ConstructorBodyNamingScope(
        method.enclosingClass, _constructorBodyScopes, _elementEnvironment);
    String key = scope.constructorBodyKeyFor(method);
    return _disambiguateMemberByKey(
        key, () => _proposeNameForConstructorBody(method));
  }
}

abstract class _MinifiedOneShotInterceptorNamer implements Namer {
  /// Property name used for the one-shot interceptor method for the given
  /// [selector] and return-type specialization.
  @override
  jsAst.Name nameForOneShotInterceptor(
      Selector selector, Iterable<ClassEntity> classes) {
    String root = selector.isOperator
        ? Namer.operatorNameToIdentifier(selector.name)
        : privateName(selector.memberName);
    String prefix = selector.isGetter
        ? r"$get"
        : selector.isSetter
            ? r"$set"
            : "";
    String callSuffix = selector.isCall
        ? Namer.callSuffixForStructure(selector.callStructure).join()
        : "";
    String suffix =
        suffixForGetInterceptor(_commonElements, _nativeData, classes);
    String fullName = "\$intercepted$prefix\$$root$callSuffix\$$suffix";
    return _disambiguateInternalGlobal(fullName);
  }
}
