| 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 ISOLATE => 'Isolate'; | 54 final String CURRENT_ISOLATE = r'$'; |
| 64 String get ISOLATE_PROPERTIES => 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 CLOSURE_INVOCATION_NAME => 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 == ISOLATE; | |
| 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 never returns the same string as we suggested so we | |
| 87 // can suggest any name and it will use it as input to the hashing | |
| 88 // algorithm. This means that constants will tend to have the same | |
| 89 // name from version to version of the program being minfied. | |
| 90 longName = stringConstant.value.slowToString(); | |
| 91 } else { | |
| 92 longName = "C"; | |
| 93 } | |
| 94 } else { | |
| 95 longName = "CTC"; | |
| 96 } | |
| 97 result = getFreshName(longName, usedGlobalNames); | |
| 98 constantNames[constant] = result; | 73 constantNames[constant] = result; |
| 99 } | 74 } |
| 100 return result; | 75 return result; |
| 101 } | 76 } |
| 102 | 77 |
| 103 String closureInvocationName(Selector selector) { | 78 String closureInvocationName(Selector selector) { |
| 104 return | 79 // TODO(floitsch): mangle, while not conflicting with instance names. |
| 105 instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, selector); | 80 return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, |
| 81 selector); |
| 106 } | 82 } |
| 107 | 83 |
| 108 String breakLabelName(LabelElement label) { | 84 String breakLabelName(LabelElement label) { |
| 109 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 85 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 110 } | 86 } |
| 111 | 87 |
| 112 String implicitBreakLabelName(TargetElement target) { | 88 String implicitBreakLabelName(TargetElement target) { |
| 113 return '\$${target.nestingLevel}'; | 89 return '\$${target.nestingLevel}'; |
| 114 } | 90 } |
| 115 | 91 |
| 116 // We sometimes handle continue targets differently from break targets, | 92 // We sometimes handle continue targets differently from break targets, |
| 117 // so we have special continue-only labels. | 93 // so we have special continue-only labels. |
| 118 String continueLabelName(LabelElement label) { | 94 String continueLabelName(LabelElement label) { |
| 119 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; | 95 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; |
| 120 } | 96 } |
| 121 | 97 |
| 122 String implicitContinueLabelName(TargetElement target) { | 98 String implicitContinueLabelName(TargetElement target) { |
| 123 return 'c\$${target.nestingLevel}'; | 99 return 'c\$${target.nestingLevel}'; |
| 124 } | 100 } |
| 125 | 101 |
| 126 /** | 102 /** |
| 127 * If the [name] is not private returns [:name.slowToString():]. Otherwise | 103 * If the [name] is not private returns [:name.slowToString():]. Otherwise |
| 128 * mangles the [name] so that each library has a unique name. | 104 * mangles the [name] so that each library has a unique name. |
| 129 */ | 105 */ |
| 130 String privateName(LibraryElement lib, SourceString name) { | 106 String privateName(LibraryElement lib, SourceString name) { |
| 131 String result; | |
| 132 if (name.isPrivate()) { | 107 if (name.isPrivate()) { |
| 133 String nameString = name.slowToString(); | 108 String nameString = name.slowToString(); |
| 134 // The first library asking for a short private name wins. | 109 // The first library asking for a short private name wins. |
| 135 LibraryElement owner = | 110 LibraryElement owner = |
| 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 == CLOSURE_INVOCATION_NAME) 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 == CLOSURE_INVOCATION_NAME) 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 == CLOSURE_INVOCATION_NAME) { | 165 return '${privateName(lib, name)}\$${selector.argumentCount}$buffer'; |
| 202 return '$CLOSURE_INVOCATION_NAME\$${selector.argumentCount}$buffer'; | |
| 203 } | |
| 204 return getMappedInstanceName( | |
| 205 '${privateName(lib, name)}\$${selector.argumentCount}$buffer'); | |
| 206 } | 166 } |
| 207 | 167 |
| 208 String instanceFieldName(LibraryElement libraryElement, SourceString name) { | 168 String instanceFieldName(LibraryElement libraryElement, SourceString name) { |
| 209 String proposedName = privateName(libraryElement, name); | 169 String proposedName = privateName(libraryElement, name); |
| 210 return getMappedInstanceName(proposedName); | 170 return safeName(proposedName); |
| 211 } | 171 } |
| 212 | 172 |
| 213 String shadowedFieldName(Element fieldElement) { | 173 String shadowedFieldName(Element fieldElement) { |
| 214 ClassElement cls = fieldElement.getEnclosingClass(); | 174 ClassElement cls = fieldElement.getEnclosingClass(); |
| 215 LibraryElement libraryElement = fieldElement.getLibrary(); | 175 LibraryElement libraryElement = fieldElement.getLibrary(); |
| 216 String libName = getName(libraryElement); | 176 String libName = getName(libraryElement); |
| 217 String clsName = getName(cls); | 177 String clsName = getName(cls); |
| 218 String instanceName = instanceFieldName(libraryElement, fieldElement.name); | 178 String instanceName = instanceFieldName(libraryElement, fieldElement.name); |
| 219 return getMappedInstanceName('$libName\$$clsName\$$instanceName'); | 179 return safeName('$libName\$$clsName\$$instanceName'); |
| 220 } | 180 } |
| 221 | 181 |
| 222 String setterName(LibraryElement lib, SourceString name) { | 182 String setterName(LibraryElement lib, SourceString name) { |
| 223 // 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 |
| 224 // therefore be derived from the instance field-name. | 184 // therefore be derived from the instance field-name. |
| 225 String fieldName = getMappedInstanceName(privateName(lib, name)); | 185 String fieldName = safeName(privateName(lib, name)); |
| 226 return 'set\$$fieldName'; | 186 return 'set\$$fieldName'; |
| 227 } | 187 } |
| 228 | 188 |
| 229 String publicGetterName(SourceString name) { | 189 String publicGetterName(SourceString name) { |
| 230 // 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 |
| 231 // therefore be derived from the instance field-name. | 191 // therefore be derived from the instance field-name. |
| 232 String fieldName = getMappedInstanceName(name.slowToString()); | 192 String fieldName = safeName(name.slowToString()); |
| 233 return 'get\$$fieldName'; | 193 return 'get\$$fieldName'; |
| 234 } | 194 } |
| 235 | 195 |
| 236 String getterName(LibraryElement lib, SourceString name) { | 196 String getterName(LibraryElement lib, SourceString name) { |
| 237 // 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 |
| 238 // therefore be derived from the instance field-name. | 198 // therefore be derived from the instance field-name. |
| 239 String fieldName = getMappedInstanceName(privateName(lib, name)); | 199 String fieldName = safeName(privateName(lib, name)); |
| 240 return 'get\$$fieldName'; | 200 return 'get\$$fieldName'; |
| 241 } | 201 } |
| 242 | 202 |
| 243 String publicSetterName(SourceString name) { | 203 String getFreshGlobalName(String proposedName) { |
| 244 // We dynamically create setter from the field-name. The setter name must | 204 String name = proposedName; |
| 245 // therefore be derived from the instance field-name. | 205 int count = usedGlobals[name]; |
| 246 String fieldName = name.slowToString(); | 206 if (count != null) { |
| 247 return 'set\$$fieldName'; | 207 // Not the first time we see this name. Append a number to make it unique. |
| 248 } | 208 do { |
| 249 | 209 name = '$proposedName${count++}'; |
| 250 String getMappedGlobalName(String proposedName) { | 210 } while (usedGlobals[name] != null); |
| 251 var newName = globalNameMap[proposedName]; | 211 // Record the count in case we see this name later. We |
| 252 if (newName == null) { | 212 // frequently see names multiple times, as all our closures use |
| 253 newName = getFreshName(proposedName, usedGlobalNames); | 213 // the same name for their class. |
| 254 globalNameMap[proposedName] = newName; | 214 usedGlobals[proposedName] = count; |
| 255 } | 215 } |
| 256 return newName; | 216 usedGlobals[name] = 0; |
| 257 } | 217 return name; |
| 258 | |
| 259 String getMappedInstanceName(String proposedName) { | |
| 260 var newName = instanceNameMap[proposedName]; | |
| 261 if (newName == null) { | |
| 262 newName = getFreshName(proposedName, usedInstanceNames); | |
| 263 instanceNameMap[proposedName] = newName; | |
| 264 } | |
| 265 return newName; | |
| 266 } | |
| 267 | |
| 268 String getFreshName(String proposedName, Set<String> usedNames) { | |
| 269 var candidate; | |
| 270 proposedName = safeName(proposedName); | |
| 271 if (!usedNames.contains(proposedName)) { | |
| 272 candidate = proposedName; | |
| 273 } else { | |
| 274 var counter = popularNameCounters[proposedName]; | |
| 275 var i = counter == null ? 0 : counter; | |
| 276 while (usedNames.contains("$proposedName$i")) { | |
| 277 i++; | |
| 278 } | |
| 279 popularNameCounters[proposedName] = i + 1; | |
| 280 candidate = "$proposedName$i"; | |
| 281 } | |
| 282 usedNames.add(candidate); | |
| 283 return candidate; | |
| 284 } | 218 } |
| 285 | 219 |
| 286 static const String LIBRARY_PREFIX = "lib"; | 220 static const String LIBRARY_PREFIX = "lib"; |
| 287 | 221 |
| 288 /** | 222 /** |
| 289 * 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. |
| 290 * The returned id is guaranteed to be a valid JS-id. | 224 * The returned id is guaranteed to be a valid JS-id. |
| 291 */ | 225 */ |
| 292 String _computeGuess(Element element) { | 226 String _computeGuess(Element element) { |
| 293 assert(!element.isInstanceMember()); | 227 assert(!element.isInstanceMember()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 306 name = "${enclosingClass.name.slowToString()}_" | 240 name = "${enclosingClass.name.slowToString()}_" |
| 307 "${element.name.slowToString()}"; | 241 "${element.name.slowToString()}"; |
| 308 } else { | 242 } else { |
| 309 name = element.name.slowToString(); | 243 name = element.name.slowToString(); |
| 310 } | 244 } |
| 311 } else if (element.isLibrary()) { | 245 } else if (element.isLibrary()) { |
| 312 name = LIBRARY_PREFIX; | 246 name = LIBRARY_PREFIX; |
| 313 } else { | 247 } else { |
| 314 name = element.name.slowToString(); | 248 name = element.name.slowToString(); |
| 315 } | 249 } |
| 316 return name; | 250 return safeName(name); |
| 317 } | 251 } |
| 318 | 252 |
| 319 String getBailoutName(Element element) { | 253 String getBailoutName(Element element) { |
| 320 String name = bailoutNames[element]; | 254 String name = bailoutNames[element]; |
| 321 if (name != null) return name; | 255 if (name != null) return name; |
| 322 bool global = !element.isInstanceMember(); | 256 bool global = !element.isInstanceMember(); |
| 323 String unminifiedName = '${getName(element)}\$bailout'; | 257 String unminifiedName = '${getName(element)}\$bailout'; |
| 324 if (global) { | 258 name = unminifiedName; |
| 325 name = getMappedGlobalName(unminifiedName); | 259 if (!global) { |
| 326 } else { | |
| 327 name = unminifiedName; | |
| 328 int i = 0; | 260 int i = 0; |
| 329 while (usedBailoutInstanceNames.contains(name)) { | 261 while (usedBailoutInstanceNames.contains(name)) { |
| 330 name = '$unminifiedName${i++}'; | 262 name = '$unminifiedName${i++}'; |
| 331 } | 263 } |
| 332 name = getMappedInstanceName(name); | |
| 333 usedBailoutInstanceNames.add(name); | 264 usedBailoutInstanceNames.add(name); |
| 334 } | 265 } |
| 335 bailoutNames[element] = name; | 266 bailoutNames[element] = name; |
| 336 return name; | 267 return name; |
| 337 } | 268 } |
| 338 | 269 |
| 339 /** | 270 /** |
| 340 * Returns a preferred JS-id for the given element. The returned id is | 271 * Returns a preferred JS-id for the given element. The returned id is |
| 341 * guaranteed to be a valid JS-id. Globals and static fields are furthermore | 272 * guaranteed to be a valid JS-id. Globals and static fields are furthermore |
| 342 * guaranteed to be unique. | 273 * guaranteed to be unique. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 364 element = element.declaration; | 295 element = element.declaration; |
| 365 // Dealing with a top-level or static element. | 296 // Dealing with a top-level or static element. |
| 366 String cached = globals[element]; | 297 String cached = globals[element]; |
| 367 if (cached != null) return cached; | 298 if (cached != null) return cached; |
| 368 | 299 |
| 369 String guess = _computeGuess(element); | 300 String guess = _computeGuess(element); |
| 370 ElementKind kind = element.kind; | 301 ElementKind kind = element.kind; |
| 371 if (identical(kind, ElementKind.VARIABLE) || | 302 if (identical(kind, ElementKind.VARIABLE) || |
| 372 identical(kind, ElementKind.PARAMETER)) { | 303 identical(kind, ElementKind.PARAMETER)) { |
| 373 // The name is not guaranteed to be unique. | 304 // The name is not guaranteed to be unique. |
| 374 return safeName(guess); | 305 return guess; |
| 375 } | 306 } |
| 376 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 307 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || |
| 377 kind == ElementKind.FUNCTION || | 308 identical(kind, ElementKind.FUNCTION) || |
| 378 kind == ElementKind.CLASS || | 309 identical(kind, ElementKind.CLASS) || |
| 379 kind == ElementKind.FIELD || | 310 identical(kind, ElementKind.FIELD) || |
| 380 kind == ElementKind.GETTER || | 311 identical(kind, ElementKind.GETTER) || |
| 381 kind == ElementKind.SETTER || | 312 identical(kind, ElementKind.SETTER) || |
| 382 kind == ElementKind.TYPEDEF || | 313 identical(kind, ElementKind.TYPEDEF) || |
| 383 kind == ElementKind.LIBRARY || | 314 identical(kind, ElementKind.LIBRARY) || |
| 384 kind == ElementKind.MALFORMED_TYPE) { | 315 identical(kind, ElementKind.MALFORMED_TYPE)) { |
| 385 bool isNative = false; | 316 String result = getFreshGlobalName(guess); |
| 386 if (identical(kind, ElementKind.CLASS)) { | |
| 387 ClassElement class_elt = element; | |
| 388 isNative = class_elt.isNative(); | |
| 389 } | |
| 390 if (Elements.isInstanceField(element)) { | |
| 391 isNative = element.isNative(); | |
| 392 } | |
| 393 String result = isNative ? guess : getFreshName(guess, usedGlobalNames); | |
| 394 globals[element] = result; | 317 globals[element] = result; |
| 395 return result; | 318 return result; |
| 396 } | 319 } |
| 397 compiler.internalError('getName for unknown kind: ${element.kind}', | 320 compiler.internalError('getName for unknown kind: ${element.kind}', |
| 398 node: element.parseNode(compiler)); | 321 node: element.parseNode(compiler)); |
| 399 } | 322 } |
| 400 } | 323 } |
| 401 | 324 |
| 402 String getLazyInitializerName(Element element) { | 325 String getLazyInitializerName(Element element) { |
| 326 // TODO(floitsch): mangle while not conflicting with other statics. |
| 403 assert(Elements.isStaticOrTopLevelField(element)); | 327 assert(Elements.isStaticOrTopLevelField(element)); |
| 404 return getMappedGlobalName("get\$${getName(element)}"); | 328 return "get\$${getName(element)}"; |
| 405 } | 329 } |
| 406 | 330 |
| 407 String isolatePropertiesAccess(Element element) { | 331 String isolatePropertiesAccess(Element element) { |
| 408 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; | 332 return "$ISOLATE.$ISOLATE_PROPERTIES.${getName(element)}"; |
| 409 } | 333 } |
| 410 | 334 |
| 411 String isolatePropertiesAccessForConstant(String constantName) { | 335 String isolatePropertiesAccessForConstant(String constantName) { |
| 412 return "$ISOLATE.$ISOLATE_PROPERTIES.$constantName"; | 336 return "$ISOLATE.$ISOLATE_PROPERTIES.$constantName"; |
| 413 } | 337 } |
| 414 | 338 |
| 415 String isolateAccess(Element element) { | 339 String isolateAccess(Element element) { |
| 416 return "$CURRENT_ISOLATE.${getName(element)}"; | 340 return "$CURRENT_ISOLATE.${getName(element)}"; |
| 417 } | 341 } |
| 418 | 342 |
| 419 String isolateBailoutAccess(Element element) { | 343 String isolateBailoutAccess(Element element) { |
| 420 String newName = getMappedGlobalName('${getName(element)}\$bailout'); | 344 return '${isolateAccess(element)}\$bailout'; |
| 421 return '$CURRENT_ISOLATE.$newName'; | |
| 422 } | 345 } |
| 423 | 346 |
| 424 String isolateLazyInitializerAccess(Element element) { | 347 String isolateLazyInitializerAccess(Element element) { |
| 425 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; | 348 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; |
| 426 } | 349 } |
| 427 | 350 |
| 428 String operatorIs(Element element) { | 351 String operatorIs(Element element) { |
| 429 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. | |
| 430 return 'is\$${getName(element)}'; | 352 return 'is\$${getName(element)}'; |
| 431 } | 353 } |
| 432 | 354 |
| 433 String safeName(String name) { | 355 String safeName(String name) { |
| 434 if (jsReserved.contains(name) || name.startsWith('\$')) { | 356 if (jsReserved.contains(name) || name.startsWith('\$')) { |
| 435 name = "\$$name"; | 357 name = "\$$name"; |
| 436 assert(!jsReserved.contains(name)); | 358 assert(!jsReserved.contains(name)); |
| 437 } | 359 } |
| 438 return name; | 360 return name; |
| 439 } | 361 } |
| 440 } | 362 } |
| OLD | NEW |