Chromium Code Reviews| 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 /** | |
| 6 * Assigns JavaScript identifiers to Dart variables, class-names and members. | |
| 7 */ | |
| 8 class MinifyNamer extends Namer { | |
| 9 MinifyNamer(Compiler compiler) : super(compiler); | |
| 10 | |
| 11 String get ISOLATE => 'I'; | |
| 12 String get ISOLATE_PROPERTIES => 'p'; | |
| 13 bool get shouldMinify => true; | |
| 14 | |
| 15 const ALPHABET_CHARACTERS = 52; // a-zA-Z. | |
| 16 const ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. | |
| 17 | |
| 18 String getFreshName(String proposedName, Set<String> usedNames) { | |
|
floitsch
2012/11/13 13:35:02
Add comment that the proposedName does not need to
erikcorry
2012/11/16 10:08:30
Done.
| |
| 19 var freshName; | |
| 20 if (proposedName.startsWith(r'call$')) { | |
|
floitsch
2012/11/13 13:35:02
This won't work if we mangle constantNames. If the
erikcorry
2012/11/16 10:08:30
Good catch. I moved the special handling of the c
| |
| 21 // We don't mangle the closure invoking function name because it is | |
| 22 // generated in applyFunction. | |
| 23 freshName = proposedName; | |
| 24 } else { | |
| 25 freshName = _getUnusedName(proposedName, usedNames); | |
| 26 } | |
| 27 usedNames.add(freshName); | |
| 28 return freshName; | |
| 29 } | |
| 30 | |
| 31 // This gets a minified name based on a hash of the proposed name. This | |
| 32 // is slightly less efficient than just getting the next name in a series, | |
| 33 // but it means that small changes in the input program will give smallish | |
| 34 // changes in the output, which can be useful for diffing etc. | |
| 35 String _getUnusedName(String proposedName, Set<String> usedNames) { | |
| 36 // Try single-character names with characters that occur in the | |
| 37 // input. | |
| 38 for (int i = 0; i < proposedName.length; i++) { | |
| 39 String candidate = proposedName[i]; | |
| 40 int code = candidate.charCodeAt(0); | |
| 41 if (code < $A) continue; | |
| 42 if (code > $z) continue; | |
| 43 if (code > $Z && code < $a) continue; | |
| 44 if (!usedNames.contains(candidate)) return candidate; | |
| 45 } | |
| 46 | |
| 47 int hash = _calculateHash(proposedName); | |
| 48 // Avoid very small hashes that won't try many names. | |
| 49 hash = hash < 1000 ? hash * 314159 : hash; // Yes, it's prime. | |
| 50 | |
| 51 // Try other n-character names based on the hash. We try one to three | |
| 52 // character identifiers. For each length we try around 10 different names | |
| 53 // in a predictable order determined by the proposed name. This is in order | |
| 54 // to make the renamer stable: small changes in the input should nornally | |
| 55 // result in relatively small changes in the output. | |
| 56 for (var n = 1; n <= 3; n++) { | |
| 57 int h = hash; | |
| 58 while (h > 10) { | |
| 59 var codes = <int>[_letterNumber(h)]; | |
| 60 int h2 = h ~/ ALPHABET_CHARACTERS; | |
| 61 for (var i = 1; i < n; i++) { | |
| 62 codes.add(_alphaNumericNumber(h2)); | |
| 63 h2 ~/= ALPHANUMERIC_CHARACTERS; | |
| 64 } | |
| 65 final candidate = new String.fromCharCodes(codes); | |
| 66 if (!usedNames.contains(candidate) && !jsReserved.contains(candidate)) { | |
| 67 return candidate; | |
| 68 } | |
| 69 // Try again with a slightly different hash. After around 10 turns | |
| 70 // around this loop h is zero and we try a longer name. | |
| 71 h ~/= 7; | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 // If we can't find a hash based name in the three-letter space, then base | |
| 76 // the name on a letter and a counter. | |
| 77 proposedName = new String.fromCharCodes([_letterNumber(hash)]); | |
| 78 var i = 0; | |
| 79 while (usedNames.contains("$proposedName$i")) { | |
| 80 i++; | |
| 81 } | |
| 82 return "$proposedName$i"; | |
| 83 } | |
| 84 | |
| 85 int _calculateHash(String name) { | |
| 86 int h = 0; | |
| 87 for (int i = 0; i < name.length; i++) { | |
| 88 h += name.charCodeAt(i); | |
| 89 h &= 0xffffffff; | |
| 90 h += h << 10; | |
| 91 h &= 0xffffffff; | |
| 92 h ^= h >> 6; | |
| 93 h &= 0xffffffff; | |
| 94 } | |
| 95 return h; | |
| 96 } | |
| 97 | |
| 98 int _letterNumber(int x) { | |
| 99 if (x >= ALPHABET_CHARACTERS) x %= ALPHABET_CHARACTERS; | |
| 100 if (x < 26) return $a + x; | |
| 101 return $A + x - 26; | |
| 102 } | |
| 103 | |
| 104 int _alphaNumericNumber(int x) { | |
| 105 if (x >= ALPHANUMERIC_CHARACTERS) x %= ALPHANUMERIC_CHARACTERS; | |
| 106 if (x < 26) return $a + x; | |
| 107 if (x < 52) return $A + x - 26; | |
| 108 return $0 + x - 52; | |
| 109 } | |
| 110 | |
| 111 } | |
| OLD | NEW |