// 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.

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);
  }
}
