| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 part of js_backend; |
| 6 |
| 7 /** |
| 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. |
| 9 */ |
| 10 class MinifyNamer extends Namer { |
| 11 MinifyNamer(Compiler compiler) : super(compiler); |
| 12 |
| 13 String get isolateName => 'I'; |
| 14 String get isolatePropertiesName => 'p'; |
| 15 bool get shouldMinify => true; |
| 16 |
| 17 const ALPHABET_CHARACTERS = 52; // a-zA-Z. |
| 18 const ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. |
| 19 |
| 20 // You can pass an invalid identifier to this and unlike its non-minifying |
| 21 // counterpart it will never return the proposedName as the new fresh name. |
| 22 String getFreshName(String proposedName, Set<String> usedNames) { |
| 23 var freshName = _getUnusedName(proposedName, usedNames); |
| 24 usedNames.add(freshName); |
| 25 return freshName; |
| 26 } |
| 27 |
| 28 // This gets a minified name based on a hash of the proposed name. This |
| 29 // is slightly less efficient than just getting the next name in a series, |
| 30 // but it means that small changes in the input program will give smallish |
| 31 // changes in the output, which can be useful for diffing etc. |
| 32 String _getUnusedName(String proposedName, Set<String> usedNames) { |
| 33 // Try single-character names with characters that occur in the |
| 34 // input. |
| 35 for (int i = 0; i < proposedName.length; i++) { |
| 36 String candidate = proposedName[i]; |
| 37 int code = candidate.charCodeAt(0); |
| 38 if (code < $A) continue; |
| 39 if (code > $z) continue; |
| 40 if (code > $Z && code < $a) continue; |
| 41 if (!usedNames.contains(candidate)) return candidate; |
| 42 } |
| 43 |
| 44 int hash = _calculateHash(proposedName); |
| 45 // Avoid very small hashes that won't try many names. |
| 46 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime. |
| 47 |
| 48 // Try other n-character names based on the hash. We try one to three |
| 49 // character identifiers. For each length we try around 10 different names |
| 50 // in a predictable order determined by the proposed name. This is in order |
| 51 // to make the renamer stable: small changes in the input should nornally |
| 52 // result in relatively small changes in the output. |
| 53 for (var n = 1; n <= 3; n++) { |
| 54 int h = hash; |
| 55 while (h > 10) { |
| 56 var codes = <int>[_letterNumber(h)]; |
| 57 int h2 = h ~/ ALPHABET_CHARACTERS; |
| 58 for (var i = 1; i < n; i++) { |
| 59 codes.add(_alphaNumericNumber(h2)); |
| 60 h2 ~/= ALPHANUMERIC_CHARACTERS; |
| 61 } |
| 62 final candidate = new String.fromCharCodes(codes); |
| 63 if (!usedNames.contains(candidate) && !jsReserved.contains(candidate)) { |
| 64 return candidate; |
| 65 } |
| 66 // Try again with a slightly different hash. After around 10 turns |
| 67 // around this loop h is zero and we try a longer name. |
| 68 h ~/= 7; |
| 69 } |
| 70 } |
| 71 |
| 72 // If we can't find a hash based name in the three-letter space, then base |
| 73 // the name on a letter and a counter. |
| 74 var startLetter = new String.fromCharCodes([_letterNumber(hash)]); |
| 75 var i = 0; |
| 76 while (usedNames.contains("$startLetter$i")) { |
| 77 i++; |
| 78 } |
| 79 return "$startLetter$i"; |
| 80 } |
| 81 |
| 82 int _calculateHash(String name) { |
| 83 int h = 0; |
| 84 for (int i = 0; i < name.length; i++) { |
| 85 h += name.charCodeAt(i); |
| 86 h &= 0xffffffff; |
| 87 h += h << 10; |
| 88 h &= 0xffffffff; |
| 89 h ^= h >> 6; |
| 90 h &= 0xffffffff; |
| 91 } |
| 92 return h; |
| 93 } |
| 94 |
| 95 int _letterNumber(int x) { |
| 96 if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS; |
| 97 if (x < 26) return $a + x; |
| 98 return $A + x - 26; |
| 99 } |
| 100 |
| 101 int _alphaNumericNumber(int x) { |
| 102 if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS; |
| 103 if (x < 26) return $a + x; |
| 104 if (x < 52) return $A + x - 26; |
| 105 return $0 + x - 52; |
| 106 } |
| 107 |
| 108 } |
| OLD | NEW |