| 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 Namer { | 10 class Namer { |
| 11 final Compiler compiler; |
| 12 |
| 11 static Set<String> _jsReserved = null; | 13 static Set<String> _jsReserved = null; |
| 12 Set<String> get jsReserved { | 14 Set<String> get jsReserved { |
| 13 if (_jsReserved == null) { | 15 if (_jsReserved == null) { |
| 14 _jsReserved = new Set<String>(); | 16 _jsReserved = new Set<String>(); |
| 15 _jsReserved.addAll(JsNames.javaScriptKeywords); | 17 _jsReserved.addAll(JsNames.javaScriptKeywords); |
| 16 _jsReserved.addAll(JsNames.reservedPropertySymbols); | 18 _jsReserved.addAll(JsNames.reservedPropertySymbols); |
| 17 } | 19 } |
| 18 return _jsReserved; | 20 return _jsReserved; |
| 19 } | 21 } |
| 20 | 22 |
| 21 final String CURRENT_ISOLATE = r'$'; | |
| 22 | |
| 23 /** | 23 /** |
| 24 * Map from top-level or static elements to their unique identifiers provided | 24 * Map from top-level or static elements to their unique identifiers provided |
| 25 * by [getName]. | 25 * by [getName]. |
| 26 * | 26 * |
| 27 * Invariant: Keys must be declaration elements. | 27 * Invariant: Keys must be declaration elements. |
| 28 */ | 28 */ |
| 29 final Compiler compiler; | |
| 30 final Map<Element, String> globals; | 29 final Map<Element, String> globals; |
| 30 final Map<String, int> usedGlobals; |
| 31 final Map<String, LibraryElement> shortPrivateNameOwners; | 31 final Map<String, LibraryElement> shortPrivateNameOwners; |
| 32 final Set<String> usedGlobalNames; | |
| 33 final Set<String> usedInstanceNames; | |
| 34 final Map<String, String> instanceNameMap; | |
| 35 final Map<String, String> globalNameMap; | |
| 36 final Map<String, int> popularNameCounters; | |
| 37 | 32 |
| 38 /** | 33 /** |
| 39 * A cache of names used for bailout methods. We make sure two | 34 * A cache of names used for bailout methods. We make sure two |
| 40 * bailout methods cannot have the same name because if the two | 35 * bailout methods cannot have the same name because if the two |
| 41 * bailout methods are in a class and a subclass, we would | 36 * bailout methods are in a class and a subclass, we would |
| 42 * call the wrong bailout method at runtime. To make it | 37 * call the wrong bailout method at runtime. To make it |
| 43 * simple, we don't keep track of inheritance and always avoid | 38 * simple, we don't keep track of inheritance and always avoid |
| 44 * similar names. | 39 * similar names. |
| 45 */ | 40 */ |
| 46 final Set<String> usedBailoutInstanceNames; | 41 final Set<String> usedBailoutInstanceNames; |
| 47 final Map<Element, String> bailoutNames; | 42 final Map<Element, String> bailoutNames; |
| 48 | 43 |
| 49 final Map<Constant, String> constantNames; | 44 final Map<Constant, String> constantNames; |
| 50 | 45 |
| 51 Namer(this.compiler) | 46 Namer(this.compiler) |
| 52 : globals = new Map<Element, String>(), | 47 : globals = new Map<Element, String>(), |
| 48 usedGlobals = new Map<String, int>(), |
| 53 shortPrivateNameOwners = new Map<String, LibraryElement>(), | 49 shortPrivateNameOwners = new Map<String, LibraryElement>(), |
| 54 bailoutNames = new Map<Element, String>(), | 50 bailoutNames = new Map<Element, String>(), |
| 55 usedBailoutInstanceNames = new Set<String>(), | 51 usedBailoutInstanceNames = new Set<String>(), |
| 56 usedGlobalNames = new Set<String>(), | 52 constantNames = new Map<Constant, String>(); |
| 57 usedInstanceNames = new Set<String>(), | |
| 58 instanceNameMap = new Map<String, String>(), | |
| 59 globalNameMap = new Map<String, String>(), | |
| 60 constantNames = new Map<Constant, String>(), | |
| 61 popularNameCounters = new Map<String, int>(); | |
| 62 | 53 |
| 63 String get isolateName => 'Isolate'; | 54 final String CURRENT_ISOLATE = r'$'; |
| 64 String get isolatePropertiesName => r'$isolateProperties'; | 55 final String ISOLATE = 'Isolate'; |
| 56 final String ISOLATE_PROPERTIES = r"$isolateProperties"; |
| 65 /** | 57 /** |
| 66 * Some closures must contain their name. The name is stored in | 58 * Some closures must contain their name. The name is stored in |
| 67 * [STATIC_CLOSURE_NAME_NAME]. | 59 * [STATIC_CLOSURE_NAME_NAME]. |
| 68 */ | 60 */ |
| 69 String get STATIC_CLOSURE_NAME_NAME => r'$name'; | 61 final String STATIC_CLOSURE_NAME_NAME = r'$name'; |
| 70 SourceString get closureInvocationSelector => Compiler.CALL_OPERATOR_NAME; | 62 static const SourceString CLOSURE_INVOCATION_NAME = |
| 71 bool get shouldMinify => false; | 63 Compiler.CALL_OPERATOR_NAME; |
| 72 | |
| 73 bool isReserved(String name) => name == isolateName; | |
| 74 | 64 |
| 75 String constantName(Constant constant) { | 65 String constantName(Constant constant) { |
| 76 // In the current implementation it doesn't make sense to give names to | 66 // In the current implementation it doesn't make sense to give names to |
| 77 // function constants since the function-implementation itself serves as | 67 // function constants since the function-implementation itself serves as |
| 78 // constant and can be accessed directly. | 68 // constant and can be accessed directly. |
| 79 assert(!constant.isFunction()); | 69 assert(!constant.isFunction()); |
| 80 String result = constantNames[constant]; | 70 String result = constantNames[constant]; |
| 81 if (result == null) { | 71 if (result == null) { |
| 82 String longName; | 72 result = getFreshGlobalName("CTC"); |
| 83 if (shouldMinify) { | |
| 84 if (constant.isString()) { | |
| 85 StringConstant stringConstant = constant; | |
| 86 // The minifier always constructs a new name, using the argument as | |
| 87 // input to its hashing algorithm. The given name does not need to be | |
| 88 // valid. | |
| 89 longName = stringConstant.value.slowToString(); | |
| 90 } else { | |
| 91 longName = "C"; | |
| 92 } | |
| 93 } else { | |
| 94 longName = "CONSTANT"; | |
| 95 } | |
| 96 result = getFreshName(longName, usedGlobalNames); | |
| 97 constantNames[constant] = result; | 73 constantNames[constant] = result; |
| 98 } | 74 } |
| 99 return result; | 75 return result; |
| 100 } | 76 } |
| 101 | 77 |
| 102 String closureInvocationName(Selector selector) { | 78 String closureInvocationName(Selector selector) { |
| 103 return | 79 // TODO(floitsch): mangle, while not conflicting with instance names. |
| 104 instanceMethodInvocationName(null, closureInvocationSelector, selector); | 80 return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, |
| 81 selector); |
| 105 } | 82 } |
| 106 | 83 |
| 107 String breakLabelName(LabelElement label) { | 84 String breakLabelName(LabelElement label) { |
| 108 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 85 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 109 } | 86 } |
| 110 | 87 |
| 111 String implicitBreakLabelName(TargetElement target) { | 88 String implicitBreakLabelName(TargetElement target) { |
| 112 return '\$${target.nestingLevel}'; | 89 return '\$${target.nestingLevel}'; |
| 113 } | 90 } |
| 114 | 91 |
| 115 // We sometimes handle continue targets differently from break targets, | 92 // We sometimes handle continue targets differently from break targets, |
| 116 // so we have special continue-only labels. | 93 // so we have special continue-only labels. |
| 117 String continueLabelName(LabelElement label) { | 94 String continueLabelName(LabelElement label) { |
| 118 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; | 95 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; |
| 119 } | 96 } |
| 120 | 97 |
| 121 String implicitContinueLabelName(TargetElement target) { | 98 String implicitContinueLabelName(TargetElement target) { |
| 122 return 'c\$${target.nestingLevel}'; | 99 return 'c\$${target.nestingLevel}'; |
| 123 } | 100 } |
| 124 | 101 |
| 125 /** | 102 /** |
| 126 * If the [name] is not private returns [:name.slowToString():]. Otherwise | 103 * If the [name] is not private returns [:name.slowToString():]. Otherwise |
| 127 * mangles the [name] so that each library has a unique name. | 104 * mangles the [name] so that each library has a unique name. |
| 128 */ | 105 */ |
| 129 String privateName(LibraryElement lib, SourceString name) { | 106 String privateName(LibraryElement lib, SourceString name) { |
| 130 String result; | |
| 131 if (name.isPrivate()) { | 107 if (name.isPrivate()) { |
| 132 String nameString = name.slowToString(); | 108 String nameString = name.slowToString(); |
| 133 // The first library asking for a short private name wins. | 109 // The first library asking for a short private name wins. |
| 134 LibraryElement owner = shouldMinify ? | 110 LibraryElement owner = |
| 135 lib : | |
| 136 shortPrivateNameOwners.putIfAbsent(nameString, () => lib); | 111 shortPrivateNameOwners.putIfAbsent(nameString, () => lib); |
| 137 // If a private name could clash with a mangled private name we don't | 112 // If a private name could clash with a mangled private name we don't |
| 138 // use the short name. For example a private name "_lib3_foo" would | 113 // use the short name. For example a private name "_lib3_foo" would |
| 139 // clash with "_foo" from "lib3". | 114 // clash with "_foo" from "lib3". |
| 140 if (owner == lib && | 115 if (identical(owner, lib) && !nameString.startsWith('_$LIBRARY_PREFIX')) { |
| 141 !nameString.startsWith('_$LIBRARY_PREFIX') && | 116 return nameString; |
| 142 !shouldMinify) { | |
| 143 result = nameString; | |
| 144 } else { | |
| 145 String libName = getName(lib); | |
| 146 // If a library name does not start with the [LIBRARY_PREFIX] then our | |
| 147 // assumptions about clashing with mangled private members do not hold. | |
| 148 assert(shouldMinify || libName.startsWith(LIBRARY_PREFIX)); | |
| 149 // TODO(erikcorry): Fix this with other manglings to avoid clashes. | |
| 150 result = '_lib$libName\$$nameString'; | |
| 151 } | 117 } |
| 118 String libName = getName(lib); |
| 119 // If a library name does not start with the [LIBRARY_PREFIX] then our |
| 120 // assumptions about clashing with mangled private members do not hold. |
| 121 assert(libName.startsWith(LIBRARY_PREFIX)); |
| 122 return '_$libName$nameString'; |
| 152 } else { | 123 } else { |
| 153 result = name.slowToString(); | 124 return name.slowToString(); |
| 154 } | 125 } |
| 155 return result; | |
| 156 } | 126 } |
| 157 | 127 |
| 158 String instanceMethodName(FunctionElement element) { | 128 String instanceMethodName(FunctionElement element) { |
| 159 SourceString name = Elements.operatorNameToIdentifier(element.name); | 129 SourceString name = Elements.operatorNameToIdentifier(element.name); |
| 160 LibraryElement lib = element.getLibrary(); | 130 LibraryElement lib = element.getLibrary(); |
| 161 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 131 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { |
| 162 ConstructorBodyElement bodyElement = element; | 132 ConstructorBodyElement bodyElement = element; |
| 163 name = bodyElement.constructor.name; | 133 name = bodyElement.constructor.name; |
| 164 } | 134 } |
| 165 FunctionSignature signature = element.computeSignature(compiler); | 135 FunctionSignature signature = element.computeSignature(compiler); |
| 166 String methodName = | 136 String methodName = |
| 167 '${privateName(lib, name)}\$${signature.parameterCount}'; | 137 '${privateName(lib, name)}\$${signature.parameterCount}'; |
| 168 if (signature.optionalParametersAreNamed && | 138 if (!signature.optionalParametersAreNamed) { |
| 169 !signature.optionalParameters.isEmpty) { | 139 return methodName; |
| 140 } else if (!signature.optionalParameters.isEmpty) { |
| 170 StringBuffer buffer = new StringBuffer(); | 141 StringBuffer buffer = new StringBuffer(); |
| 171 signature.orderedOptionalParameters.forEach((Element element) { | 142 signature.orderedOptionalParameters.forEach((Element element) { |
| 172 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); | 143 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); |
| 173 }); | 144 }); |
| 174 methodName = '$methodName$buffer'; | 145 return '$methodName$buffer'; |
| 175 } | 146 } |
| 176 if (name == closureInvocationSelector) return methodName; | |
| 177 return getMappedInstanceName(methodName); | |
| 178 } | 147 } |
| 179 | 148 |
| 180 String publicInstanceMethodNameByArity(SourceString name, int arity) { | 149 String publicInstanceMethodNameByArity(SourceString name, int arity) { |
| 181 name = Elements.operatorNameToIdentifier(name); | 150 name = Elements.operatorNameToIdentifier(name); |
| 182 assert(!name.isPrivate()); | 151 assert(!name.isPrivate()); |
| 183 var base = name.slowToString(); | 152 return '${name.slowToString()}\$$arity'; |
| 184 // We don't mangle the closure invoking function name because it is | |
| 185 // generated in applyFunction. | |
| 186 var proposedName = '$base\$$arity'; | |
| 187 if (base == closureInvocationSelector) return proposedName; | |
| 188 return getMappedInstanceName(proposedName); | |
| 189 } | 153 } |
| 190 | 154 |
| 191 String instanceMethodInvocationName(LibraryElement lib, SourceString name, | 155 String instanceMethodInvocationName(LibraryElement lib, SourceString name, |
| 192 Selector selector) { | 156 Selector selector) { |
| 193 name = Elements.operatorNameToIdentifier(name); | 157 name = Elements.operatorNameToIdentifier(name); |
| 194 // TODO(floitsch): mangle, while preserving uniqueness. | 158 // TODO(floitsch): mangle, while preserving uniqueness. |
| 195 StringBuffer buffer = new StringBuffer(); | 159 StringBuffer buffer = new StringBuffer(); |
| 196 List<SourceString> names = selector.getOrderedNamedArguments(); | 160 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 197 for (SourceString argumentName in names) { | 161 for (SourceString argumentName in names) { |
| 198 buffer.add(r'$'); | 162 buffer.add(r'$'); |
| 199 argumentName.printOn(buffer); | 163 argumentName.printOn(buffer); |
| 200 } | 164 } |
| 201 if (name == closureInvocationSelector) { | 165 return '${privateName(lib, name)}\$${selector.argumentCount}$buffer'; |
| 202 // We don't mangle the closure invoking function name because it is | |
| 203 // generated in applyFunction. | |
| 204 return '$closureInvocationSelector\$${selector.argumentCount}$buffer'; | |
| 205 } | |
| 206 return getMappedInstanceName( | |
| 207 '${privateName(lib, name)}\$${selector.argumentCount}$buffer'); | |
| 208 } | 166 } |
| 209 | 167 |
| 210 String instanceFieldName(LibraryElement libraryElement, SourceString name) { | 168 String instanceFieldName(LibraryElement libraryElement, SourceString name) { |
| 211 String proposedName = privateName(libraryElement, name); | 169 String proposedName = privateName(libraryElement, name); |
| 212 return getMappedInstanceName(proposedName); | 170 return safeName(proposedName); |
| 213 } | 171 } |
| 214 | 172 |
| 215 // Construct a new name for the element based on the library and class it is | |
| 216 // in. The name here is not important, we just need to make sure it is | |
| 217 // unique. If we are minifying, we actually construct the name from the | |
| 218 // minified versions of the class and instance names, but the result is | |
| 219 // minified once again, so that is not visible in the end result. | |
| 220 String shadowedFieldName(Element fieldElement) { | 173 String shadowedFieldName(Element fieldElement) { |
| 221 // Check for following situation: Native field ${fieldElement.name} has | |
| 222 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | |
| 223 // name. We normally handle that by renaming the superclass field, but we | |
| 224 // can't do that because native fields have fixed JSNames. In practice | |
| 225 // this can't happen because we can't inherit from native classes. | |
| 226 assert (!fieldElement.isNative()); | |
| 227 | |
| 228 ClassElement cls = fieldElement.getEnclosingClass(); | 174 ClassElement cls = fieldElement.getEnclosingClass(); |
| 229 LibraryElement libraryElement = fieldElement.getLibrary(); | 175 LibraryElement libraryElement = fieldElement.getLibrary(); |
| 230 String libName = getName(libraryElement); | 176 String libName = getName(libraryElement); |
| 231 String clsName = getName(cls); | 177 String clsName = getName(cls); |
| 232 String instanceName = instanceFieldName(libraryElement, fieldElement.name); | 178 String instanceName = instanceFieldName(libraryElement, fieldElement.name); |
| 233 return getMappedInstanceName('$libName\$$clsName\$$instanceName'); | 179 return safeName('$libName\$$clsName\$$instanceName'); |
| 234 } | 180 } |
| 235 | 181 |
| 236 String setterName(LibraryElement lib, SourceString name) { | 182 String setterName(LibraryElement lib, SourceString name) { |
| 237 // We dynamically create setters from the field-name. The setter name must | 183 // We dynamically create setters from the field-name. The setter name must |
| 238 // therefore be derived from the instance field-name. | 184 // therefore be derived from the instance field-name. |
| 239 String fieldName = getMappedInstanceName(privateName(lib, name)); | 185 String fieldName = safeName(privateName(lib, name)); |
| 240 return 'set\$$fieldName'; | 186 return 'set\$$fieldName'; |
| 241 } | 187 } |
| 242 | 188 |
| 243 String setterNameFromAccessorName(String name) { | |
| 244 // We dynamically create setters from the field-name. The setter name must | |
| 245 // therefore be derived from the instance field-name. | |
| 246 return 'set\$$name'; | |
| 247 } | |
| 248 | |
| 249 String publicGetterName(SourceString name) { | 189 String publicGetterName(SourceString name) { |
| 250 // We dynamically create getters from the field-name. The getter name must | 190 // We dynamically create getters from the field-name. The getter name must |
| 251 // therefore be derived from the instance field-name. | 191 // therefore be derived from the instance field-name. |
| 252 String fieldName = getMappedInstanceName(name.slowToString()); | 192 String fieldName = safeName(name.slowToString()); |
| 253 return 'get\$$fieldName'; | 193 return 'get\$$fieldName'; |
| 254 } | 194 } |
| 255 | 195 |
| 256 String getterNameFromAccessorName(String name) { | |
| 257 // We dynamically create getters from the field-name. The getter name must | |
| 258 // therefore be derived from the instance field-name. | |
| 259 return 'get\$$name'; | |
| 260 } | |
| 261 | |
| 262 String getterName(LibraryElement lib, SourceString name) { | 196 String getterName(LibraryElement lib, SourceString name) { |
| 263 // We dynamically create getters from the field-name. The getter name must | 197 // We dynamically create getters from the field-name. The getter name must |
| 264 // therefore be derived from the instance field-name. | 198 // therefore be derived from the instance field-name. |
| 265 String fieldName = getMappedInstanceName(privateName(lib, name)); | 199 String fieldName = safeName(privateName(lib, name)); |
| 266 return 'get\$$fieldName'; | 200 return 'get\$$fieldName'; |
| 267 } | 201 } |
| 268 | 202 |
| 269 String getMappedGlobalName(String proposedName) { | 203 String getFreshGlobalName(String proposedName) { |
| 270 var newName = globalNameMap[proposedName]; | 204 String name = proposedName; |
| 271 if (newName == null) { | 205 int count = usedGlobals[name]; |
| 272 newName = getFreshName(proposedName, usedGlobalNames); | 206 if (count != null) { |
| 273 globalNameMap[proposedName] = newName; | 207 // Not the first time we see this name. Append a number to make it unique. |
| 208 do { |
| 209 name = '$proposedName${count++}'; |
| 210 } while (usedGlobals[name] != null); |
| 211 // Record the count in case we see this name later. We |
| 212 // frequently see names multiple times, as all our closures use |
| 213 // the same name for their class. |
| 214 usedGlobals[proposedName] = count; |
| 274 } | 215 } |
| 275 return newName; | 216 usedGlobals[name] = 0; |
| 276 } | 217 return name; |
| 277 | |
| 278 String getMappedInstanceName(String proposedName) { | |
| 279 var newName = instanceNameMap[proposedName]; | |
| 280 if (newName == null) { | |
| 281 newName = getFreshName(proposedName, usedInstanceNames); | |
| 282 instanceNameMap[proposedName] = newName; | |
| 283 } | |
| 284 return newName; | |
| 285 } | |
| 286 | |
| 287 String getFreshName(String proposedName, Set<String> usedNames) { | |
| 288 var candidate; | |
| 289 proposedName = safeName(proposedName); | |
| 290 if (!usedNames.contains(proposedName)) { | |
| 291 candidate = proposedName; | |
| 292 } else { | |
| 293 var counter = popularNameCounters[proposedName]; | |
| 294 var i = counter == null ? 0 : counter; | |
| 295 while (usedNames.contains("$proposedName$i")) { | |
| 296 i++; | |
| 297 } | |
| 298 popularNameCounters[proposedName] = i + 1; | |
| 299 candidate = "$proposedName$i"; | |
| 300 } | |
| 301 usedNames.add(candidate); | |
| 302 return candidate; | |
| 303 } | 218 } |
| 304 | 219 |
| 305 static const String LIBRARY_PREFIX = "lib"; | 220 static const String LIBRARY_PREFIX = "lib"; |
| 306 | 221 |
| 307 /** | 222 /** |
| 308 * Returns a preferred JS-id for the given top-level or static element. | 223 * Returns a preferred JS-id for the given top-level or static element. |
| 309 * The returned id is guaranteed to be a valid JS-id. | 224 * The returned id is guaranteed to be a valid JS-id. |
| 310 */ | 225 */ |
| 311 String _computeGuess(Element element) { | 226 String _computeGuess(Element element) { |
| 312 assert(!element.isInstanceMember()); | 227 assert(!element.isInstanceMember()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 325 name = "${enclosingClass.name.slowToString()}_" | 240 name = "${enclosingClass.name.slowToString()}_" |
| 326 "${element.name.slowToString()}"; | 241 "${element.name.slowToString()}"; |
| 327 } else { | 242 } else { |
| 328 name = element.name.slowToString(); | 243 name = element.name.slowToString(); |
| 329 } | 244 } |
| 330 } else if (element.isLibrary()) { | 245 } else if (element.isLibrary()) { |
| 331 name = LIBRARY_PREFIX; | 246 name = LIBRARY_PREFIX; |
| 332 } else { | 247 } else { |
| 333 name = element.name.slowToString(); | 248 name = element.name.slowToString(); |
| 334 } | 249 } |
| 335 return name; | 250 return safeName(name); |
| 336 } | 251 } |
| 337 | 252 |
| 338 String getSpecializedName(Element element, Collection<ClassElement> classes) { | 253 String getSpecializedName(Element element, Collection<ClassElement> classes) { |
| 339 // This gets the minified name, but it doesn't really make much difference. | |
| 340 // the important thing is that it is a unique name. | |
| 341 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); | 254 StringBuffer buffer = new StringBuffer('${getName(element)}\$'); |
| 342 for (ClassElement cls in classes) { | 255 for (ClassElement cls in classes) { |
| 343 buffer.add(getName(cls)); | 256 buffer.add(getName(cls)); |
| 344 } | 257 } |
| 345 return getMappedGlobalName(buffer.toString()); | 258 return safeName(buffer.toString()); |
| 346 } | 259 } |
| 347 | 260 |
| 348 String getBailoutName(Element element) { | 261 String getBailoutName(Element element) { |
| 349 String name = bailoutNames[element]; | 262 String name = bailoutNames[element]; |
| 350 if (name != null) return name; | 263 if (name != null) return name; |
| 351 bool global = !element.isInstanceMember(); | 264 bool global = !element.isInstanceMember(); |
| 352 // Despite the name of the variable, this gets the minified name when we | |
| 353 // are minifying, but it doesn't really make much difference. The | |
| 354 // important thing is that it is a unique name. We add $bailout and, if we | |
| 355 // are minifying, we minify the minified name and '$bailout'. | |
| 356 String unminifiedName = '${getName(element)}\$bailout'; | 265 String unminifiedName = '${getName(element)}\$bailout'; |
| 357 if (global) { | 266 name = unminifiedName; |
| 358 name = getMappedGlobalName(unminifiedName); | 267 if (!global) { |
| 359 } else { | |
| 360 name = unminifiedName; | |
| 361 int i = 0; | 268 int i = 0; |
| 362 while (usedBailoutInstanceNames.contains(name)) { | 269 while (usedBailoutInstanceNames.contains(name)) { |
| 363 name = '$unminifiedName${i++}'; | 270 name = '$unminifiedName${i++}'; |
| 364 } | 271 } |
| 365 usedBailoutInstanceNames.add(name); | 272 usedBailoutInstanceNames.add(name); |
| 366 name = getMappedInstanceName(name); | |
| 367 } | 273 } |
| 368 bailoutNames[element] = name; | 274 bailoutNames[element] = name; |
| 369 return name; | 275 return name; |
| 370 } | 276 } |
| 371 | 277 |
| 372 /** | 278 /** |
| 373 * Returns a preferred JS-id for the given element. The returned id is | 279 * Returns a preferred JS-id for the given element. The returned id is |
| 374 * guaranteed to be a valid JS-id. Globals and static fields are furthermore | 280 * guaranteed to be a valid JS-id. Globals and static fields are furthermore |
| 375 * guaranteed to be unique. | 281 * guaranteed to be unique. |
| 376 * | 282 * |
| (...skipping 17 matching lines...) Expand all Loading... |
| 394 } | 300 } |
| 395 } else { | 301 } else { |
| 396 // Use declaration element to ensure invariant on [globals]. | 302 // Use declaration element to ensure invariant on [globals]. |
| 397 element = element.declaration; | 303 element = element.declaration; |
| 398 // Dealing with a top-level or static element. | 304 // Dealing with a top-level or static element. |
| 399 String cached = globals[element]; | 305 String cached = globals[element]; |
| 400 if (cached != null) return cached; | 306 if (cached != null) return cached; |
| 401 | 307 |
| 402 String guess = _computeGuess(element); | 308 String guess = _computeGuess(element); |
| 403 ElementKind kind = element.kind; | 309 ElementKind kind = element.kind; |
| 404 if (kind == ElementKind.VARIABLE || | 310 if (identical(kind, ElementKind.VARIABLE) || |
| 405 kind == ElementKind.PARAMETER) { | 311 identical(kind, ElementKind.PARAMETER)) { |
| 406 // The name is not guaranteed to be unique. | 312 // The name is not guaranteed to be unique. |
| 407 return safeName(guess); | 313 return guess; |
| 408 } | 314 } |
| 409 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 315 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || |
| 410 kind == ElementKind.FUNCTION || | 316 identical(kind, ElementKind.FUNCTION) || |
| 411 kind == ElementKind.CLASS || | 317 identical(kind, ElementKind.CLASS) || |
| 412 kind == ElementKind.FIELD || | 318 identical(kind, ElementKind.FIELD) || |
| 413 kind == ElementKind.GETTER || | 319 identical(kind, ElementKind.GETTER) || |
| 414 kind == ElementKind.SETTER || | 320 identical(kind, ElementKind.SETTER) || |
| 415 kind == ElementKind.TYPEDEF || | 321 identical(kind, ElementKind.TYPEDEF) || |
| 416 kind == ElementKind.LIBRARY || | 322 identical(kind, ElementKind.LIBRARY) || |
| 417 kind == ElementKind.MALFORMED_TYPE) { | 323 identical(kind, ElementKind.MALFORMED_TYPE)) { |
| 418 bool isNative = false; | 324 String result = getFreshGlobalName(guess); |
| 419 if (kind == ElementKind.CLASS) { | |
| 420 ClassElement class_elt = element; | |
| 421 isNative = class_elt.isNative(); | |
| 422 } | |
| 423 if (Elements.isInstanceField(element)) { | |
| 424 isNative = element.isNative(); | |
| 425 } | |
| 426 String result = isNative ? guess : getFreshName(guess, usedGlobalNames); | |
| 427 globals[element] = result; | 325 globals[element] = result; |
| 428 return result; | 326 return result; |
| 429 } | 327 } |
| 430 compiler.internalError('getName for unknown kind: ${element.kind}', | 328 compiler.internalError('getName for unknown kind: ${element.kind}', |
| 431 node: element.parseNode(compiler)); | 329 node: element.parseNode(compiler)); |
| 432 } | 330 } |
| 433 } | 331 } |
| 434 | 332 |
| 435 String getLazyInitializerName(Element element) { | 333 String getLazyInitializerName(Element element) { |
| 334 // TODO(floitsch): mangle while not conflicting with other statics. |
| 436 assert(Elements.isStaticOrTopLevelField(element)); | 335 assert(Elements.isStaticOrTopLevelField(element)); |
| 437 return getMappedGlobalName("get\$${getName(element)}"); | 336 return "get\$${getName(element)}"; |
| 438 } | 337 } |
| 439 | 338 |
| 440 String isolatePropertiesAccess(Element element) { | 339 String isolatePropertiesAccess(Element element) { |
| 441 return "$isolateName.$isolatePropertiesName.${getName(element)}"; | 340 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; |
| 442 } | 341 } |
| 443 | 342 |
| 444 String isolateAccess(Element element) { | 343 String isolateAccess(Element element) { |
| 445 return "$CURRENT_ISOLATE.${getName(element)}"; | 344 return "$CURRENT_ISOLATE.${getName(element)}"; |
| 446 } | 345 } |
| 447 | 346 |
| 448 String isolateBailoutAccess(Element element) { | 347 String isolateBailoutAccess(Element element) { |
| 449 String newName = getMappedGlobalName('${getName(element)}\$bailout'); | 348 return '${isolateAccess(element)}\$bailout'; |
| 450 return '$CURRENT_ISOLATE.$newName'; | |
| 451 } | 349 } |
| 452 | 350 |
| 453 String isolateLazyInitializerAccess(Element element) { | 351 String isolateLazyInitializerAccess(Element element) { |
| 454 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; | 352 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; |
| 455 } | 353 } |
| 456 | 354 |
| 457 String operatorIs(Element element) { | 355 String operatorIs(Element element) { |
| 458 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. | |
| 459 return 'is\$${getName(element)}'; | 356 return 'is\$${getName(element)}'; |
| 460 } | 357 } |
| 461 | 358 |
| 462 String safeName(String name) { | 359 String safeName(String name) { |
| 463 if (jsReserved.contains(name) || name.startsWith('\$')) { | 360 if (jsReserved.contains(name) || name.startsWith('\$')) { |
| 464 name = "\$$name"; | 361 name = "\$$name"; |
| 465 assert(!jsReserved.contains(name)); | 362 assert(!jsReserved.contains(name)); |
| 466 } | 363 } |
| 467 return name; | 364 return name; |
| 468 } | 365 } |
| 469 } | 366 } |
| OLD | NEW |