| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. | 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. |
| 9 */ | 9 */ |
| 10 class MinifyNamer extends Namer with _MinifiedFieldNamer { | 10 class MinifyNamer extends Namer with _MinifiedFieldNamer, |
| 11 _MinifiedOneShotInterceptorNamer { |
| 11 MinifyNamer(Compiler compiler) : super(compiler) { | 12 MinifyNamer(Compiler compiler) : super(compiler) { |
| 12 reserveBackendNames(); | 13 reserveBackendNames(); |
| 13 fieldRegistry = new _FieldNamingRegistry(this); | 14 fieldRegistry = new _FieldNamingRegistry(this); |
| 14 } | 15 } |
| 15 | 16 |
| 16 _FieldNamingRegistry fieldRegistry; | 17 _FieldNamingRegistry fieldRegistry; |
| 17 | 18 |
| 18 String get isolateName => 'I'; | 19 String get isolateName => 'I'; |
| 19 String get isolatePropertiesName => 'p'; | 20 String get isolatePropertiesName => 'p'; |
| 20 bool get shouldMinify => true; | 21 bool get shouldMinify => true; |
| 21 | 22 |
| 22 final String getterPrefix = 'g'; | 23 final String getterPrefix = 'g'; |
| 23 final String setterPrefix = 's'; | 24 final String setterPrefix = 's'; |
| 24 final String callPrefix = ''; // this will create function names $<n> | 25 final String callPrefix = ''; // this will create function names $<n> |
| 25 | 26 |
| 26 final ALPHABET_CHARACTERS = 52; // a-zA-Z. | 27 final ALPHABET_CHARACTERS = 52; // a-zA-Z. |
| 27 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. | 28 final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9. |
| 28 | 29 |
| 29 /// You can pass an invalid identifier to this and unlike its non-minifying | 30 /// You can pass an invalid identifier to this and unlike its non-minifying |
| 30 /// counterpart it will never return the proposedName as the new fresh name. | 31 /// counterpart it will never return the proposedName as the new fresh name. |
| 31 /// | 32 /// |
| 32 /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the | 33 /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the |
| 33 /// minified names will always avoid clashing with annotated names or natives. | 34 /// minified names will always avoid clashing with annotated names or natives. |
| 34 @override | 35 @override |
| 35 jsAst.Name getFreshName(String proposedName, | 36 String _generateFreshStringForName(String proposedName, |
| 36 Set<String> usedNames, | 37 Set<String> usedNames, |
| 37 Map<String, String> suggestedNames, | 38 Map<String, String> suggestedNames, |
| 38 {bool sanitizeForNatives: false, | 39 {bool sanitizeForNatives: false, |
| 39 bool sanitizeForAnnotations: false}) { | 40 bool sanitizeForAnnotations: false}) { |
| 40 String freshName; | 41 String freshName; |
| 41 String suggestion = suggestedNames[proposedName]; | 42 String suggestion = suggestedNames[proposedName]; |
| 42 if (suggestion != null && !usedNames.contains(suggestion)) { | 43 if (suggestion != null && !usedNames.contains(suggestion)) { |
| 43 freshName = suggestion; | 44 freshName = suggestion; |
| 44 } else { | 45 } else { |
| 45 freshName = _getUnusedName(proposedName, usedNames, | 46 freshName = _getUnusedName(proposedName, usedNames, |
| 46 suggestedNames.values); | 47 suggestedNames.values); |
| 47 } | 48 } |
| 48 usedNames.add(freshName); | 49 usedNames.add(freshName); |
| 49 return new StringBackedName(freshName); | 50 return freshName; |
| 50 } | 51 } |
| 51 | 52 |
| 52 // From issue 7554. These should not be used on objects (as instance | 53 // From issue 7554. These should not be used on objects (as instance |
| 53 // variables) because they clash with names from the DOM. However, it is | 54 // variables) because they clash with names from the DOM. However, it is |
| 54 // OK to use them as fields, as we only access fields directly if we know | 55 // OK to use them as fields, as we only access fields directly if we know |
| 55 // the receiver type. | 56 // the receiver type. |
| 56 static const List<String> _reservedNativeProperties = const <String>[ | 57 static const List<String> _reservedNativeProperties = const <String>[ |
| 57 'Q', 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z', | 58 'Q', 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z', |
| 58 // 2-letter: | 59 // 2-letter: |
| 59 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1', | 60 'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1', |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // Try again with a slightly different hash. After around 10 turns | 186 // Try again with a slightly different hash. After around 10 turns |
| 186 // around this loop h is zero and we try a longer name. | 187 // around this loop h is zero and we try a longer name. |
| 187 h ~/= 7; | 188 h ~/= 7; |
| 188 } | 189 } |
| 189 } | 190 } |
| 190 return _badName(hash, usedNames); | 191 return _badName(hash, usedNames); |
| 191 } | 192 } |
| 192 | 193 |
| 193 /// Instance members starting with g and s are reserved for getters and | 194 /// Instance members starting with g and s are reserved for getters and |
| 194 /// setters. | 195 /// setters. |
| 195 bool _hasBannedPrefix(String name) { | 196 static bool _hasBannedPrefix(String name) { |
| 196 int code = name.codeUnitAt(0); | 197 int code = name.codeUnitAt(0); |
| 197 return code == $g || code == $s; | 198 return code == $g || code == $s; |
| 198 } | 199 } |
| 199 | 200 |
| 200 int _calculateHash(String name) { | 201 int _calculateHash(String name) { |
| 201 int h = 0; | 202 int h = 0; |
| 202 for (int i = 0; i < name.length; i++) { | 203 for (int i = 0; i < name.length; i++) { |
| 203 h += name.codeUnitAt(i); | 204 h += name.codeUnitAt(i); |
| 204 h &= 0xffffffff; | 205 h &= 0xffffffff; |
| 205 h += h << 10; | 206 h += h << 10; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 @override | 249 @override |
| 249 jsAst.Name instanceFieldPropertyName(Element element) { | 250 jsAst.Name instanceFieldPropertyName(Element element) { |
| 250 jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element); | 251 jsAst.Name proposed = _minifiedInstanceFieldPropertyName(element); |
| 251 if (proposed != null) { | 252 if (proposed != null) { |
| 252 return proposed; | 253 return proposed; |
| 253 } | 254 } |
| 254 return super.instanceFieldPropertyName(element); | 255 return super.instanceFieldPropertyName(element); |
| 255 } | 256 } |
| 256 } | 257 } |
| 257 | 258 |
| 259 abstract class _MinifiedOneShotInterceptorNamer implements Namer { |
| 260 /// Property name used for the one-shot interceptor method for the given |
| 261 /// [selector] and return-type specialization. |
| 262 jsAst.Name nameForGetOneShotInterceptor(Selector selector, |
| 263 Iterable<ClassElement> classes) { |
| 264 String root = selector.isOperator ? operatorNameToIdentifier(selector.name) |
| 265 : privateName(selector.memberName); |
| 266 String prefix = selector.isGetter ? r"$get" |
| 267 : selector.isSetter ? r"$set" : ""; |
| 268 String arity = selector.isCall ? "${selector.argumentCount}" : ""; |
| 269 String suffix = suffixForGetInterceptor(classes); |
| 270 String fullName = "\$intercepted$prefix\$$root$arity\$$suffix"; |
| 271 return _disambiguateInternalGlobal(fullName); |
| 272 } |
| 273 } |
| OLD | NEW |