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 |