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