Chromium Code Reviews| 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 implements ClosureNamer { | 10 class Namer implements ClosureNamer { |
| 11 | |
| 12 static const javaScriptKeywords = const <String>[ | |
| 13 // These are current keywords | |
|
kasperl
2013/01/23 14:46:15
No .?
ngeoffray
2013/01/23 14:48:08
Doh!
| |
| 14 "break", "delete", "function", "return", "typeof", "case", "do", "if", | |
| 15 "switch", "var", "catch", "else", "in", "this", "void", "continue", | |
| 16 "false", "instanceof", "throw", "while", "debugger", "finally", "new", | |
| 17 "true", "with", "default", "for", "null", "try", | |
| 18 | |
| 19 // These are future keywords | |
| 20 "abstract", "double", "goto", "native", "static", "boolean", "enum", | |
| 21 "implements", "package", "super", "byte", "export", "import", "private", | |
| 22 "synchronized", "char", "extends", "int", "protected", "throws", | |
| 23 "class", "final", "interface", "public", "transient", "const", "float", | |
| 24 "long", "short", "volatile" | |
| 25 ]; | |
| 26 | |
| 27 static const reservedPropertySymbols = | |
| 28 const <String>["__PROTO__", "prototype", "constructor"]; | |
| 29 | |
| 11 static Set<String> _jsReserved = null; | 30 static Set<String> _jsReserved = null; |
| 12 Set<String> get jsReserved { | 31 Set<String> get jsReserved { |
| 13 if (_jsReserved == null) { | 32 if (_jsReserved == null) { |
| 14 _jsReserved = new Set<String>(); | 33 _jsReserved = new Set<String>(); |
| 15 _jsReserved.addAll(JsNames.javaScriptKeywords); | 34 _jsReserved.addAll(javaScriptKeywords); |
| 16 _jsReserved.addAll(JsNames.reservedPropertySymbols); | 35 _jsReserved.addAll(reservedPropertySymbols); |
| 17 } | 36 } |
| 18 return _jsReserved; | 37 return _jsReserved; |
| 19 } | 38 } |
| 20 | 39 |
| 21 final String CURRENT_ISOLATE = r'$'; | 40 final String CURRENT_ISOLATE = r'$'; |
| 22 | 41 |
| 23 /** | 42 /** |
| 24 * Map from top-level or static elements to their unique identifiers provided | 43 * Map from top-level or static elements to their unique identifiers provided |
| 25 * by [getName]. | 44 * by [getName]. |
| 26 * | 45 * |
| 27 * Invariant: Keys must be declaration elements. | 46 * Invariant: Keys must be declaration elements. |
| 28 */ | 47 */ |
| 29 final Compiler compiler; | 48 final Compiler compiler; |
| 30 final Map<Element, String> globals; | 49 final Map<Element, String> globals; |
| 31 final Map<String, LibraryElement> shortPrivateNameOwners; | 50 final Map<String, LibraryElement> shortPrivateNameOwners; |
| 32 final Set<String> usedGlobalNames; | 51 final Set<String> usedGlobalNames; |
| 33 final Set<String> usedInstanceNames; | 52 final Set<String> usedInstanceNames; |
| 34 final Map<String, String> globalNameMap; | 53 final Map<String, String> globalNameMap; |
| 35 final Map<String, String> instanceNameMap; | 54 final Map<String, String> instanceNameMap; |
| 55 final Map<String, String> operatorNameMap; | |
| 36 final Map<String, int> popularNameCounters; | 56 final Map<String, int> popularNameCounters; |
| 37 | 57 |
| 38 /** | 58 /** |
| 39 * A cache of names used for bailout methods. We make sure two | 59 * A cache of names used for bailout methods. We make sure two |
| 40 * bailout methods cannot have the same name because if the two | 60 * bailout methods cannot have the same name because if the two |
| 41 * bailout methods are in a class and a subclass, we would | 61 * bailout methods are in a class and a subclass, we would |
| 42 * call the wrong bailout method at runtime. To make it | 62 * call the wrong bailout method at runtime. To make it |
| 43 * simple, we don't keep track of inheritance and always avoid | 63 * simple, we don't keep track of inheritance and always avoid |
| 44 * similar names. | 64 * similar names. |
| 45 */ | 65 */ |
| 46 final Set<String> usedBailoutInstanceNames; | 66 final Set<String> usedBailoutInstanceNames; |
| 47 final Map<Element, String> bailoutNames; | 67 final Map<Element, String> bailoutNames; |
| 48 | 68 |
| 49 final Map<Constant, String> constantNames; | 69 final Map<Constant, String> constantNames; |
| 50 | 70 |
| 51 Namer(this.compiler) | 71 Namer(this.compiler) |
| 52 : globals = new Map<Element, String>(), | 72 : globals = new Map<Element, String>(), |
| 53 shortPrivateNameOwners = new Map<String, LibraryElement>(), | 73 shortPrivateNameOwners = new Map<String, LibraryElement>(), |
| 54 bailoutNames = new Map<Element, String>(), | 74 bailoutNames = new Map<Element, String>(), |
| 55 usedBailoutInstanceNames = new Set<String>(), | 75 usedBailoutInstanceNames = new Set<String>(), |
| 56 usedGlobalNames = new Set<String>(), | 76 usedGlobalNames = new Set<String>(), |
| 57 usedInstanceNames = new Set<String>(), | 77 usedInstanceNames = new Set<String>(), |
| 58 instanceNameMap = new Map<String, String>(), | 78 instanceNameMap = new Map<String, String>(), |
| 79 operatorNameMap = new Map<String, String>(), | |
| 59 globalNameMap = new Map<String, String>(), | 80 globalNameMap = new Map<String, String>(), |
| 60 constantNames = new Map<Constant, String>(), | 81 constantNames = new Map<Constant, String>(), |
| 61 popularNameCounters = new Map<String, int>(); | 82 popularNameCounters = new Map<String, int>(); |
| 62 | 83 |
| 63 String get isolateName => 'Isolate'; | 84 String get isolateName => 'Isolate'; |
| 64 String get isolatePropertiesName => r'$isolateProperties'; | 85 String get isolatePropertiesName => r'$isolateProperties'; |
| 65 /** | 86 /** |
| 66 * Some closures must contain their name. The name is stored in | 87 * Some closures must contain their name. The name is stored in |
| 67 * [STATIC_CLOSURE_NAME_NAME]. | 88 * [STATIC_CLOSURE_NAME_NAME]. |
| 68 */ | 89 */ |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 86 // The minifier always constructs a new name, using the argument as | 107 // 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 | 108 // input to its hashing algorithm. The given name does not need to be |
| 88 // valid. | 109 // valid. |
| 89 longName = stringConstant.value.slowToString(); | 110 longName = stringConstant.value.slowToString(); |
| 90 } else { | 111 } else { |
| 91 longName = "C"; | 112 longName = "C"; |
| 92 } | 113 } |
| 93 } else { | 114 } else { |
| 94 longName = "CONSTANT"; | 115 longName = "CONSTANT"; |
| 95 } | 116 } |
| 96 result = getFreshName(longName, usedGlobalNames); | 117 result = getFreshName(longName, usedGlobalNames, true); |
| 97 constantNames[constant] = result; | 118 constantNames[constant] = result; |
| 98 } | 119 } |
| 99 return result; | 120 return result; |
| 100 } | 121 } |
| 101 | 122 |
| 102 String breakLabelName(LabelElement label) { | 123 String breakLabelName(LabelElement label) { |
| 103 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 124 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 104 } | 125 } |
| 105 | 126 |
| 106 String implicitBreakLabelName(TargetElement target) { | 127 String implicitBreakLabelName(TargetElement target) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 | 163 |
| 143 // If a library name does not start with the [LIBRARY_PREFIX] then our | 164 // If a library name does not start with the [LIBRARY_PREFIX] then our |
| 144 // assumptions about clashing with mangled private members do not hold. | 165 // assumptions about clashing with mangled private members do not hold. |
| 145 String libraryName = getName(library); | 166 String libraryName = getName(library); |
| 146 assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX)); | 167 assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX)); |
| 147 // TODO(erikcorry): Fix this with other manglings to avoid clashes. | 168 // TODO(erikcorry): Fix this with other manglings to avoid clashes. |
| 148 return '_lib$libraryName\$$nameString'; | 169 return '_lib$libraryName\$$nameString'; |
| 149 } | 170 } |
| 150 | 171 |
| 151 String instanceMethodName(FunctionElement element) { | 172 String instanceMethodName(FunctionElement element) { |
| 152 SourceString name = Elements.operatorNameToIdentifier(element.name); | 173 SourceString elementName = element.name; |
| 174 SourceString name = operatorNameToIdentifier(elementName); | |
| 175 if (name != elementName) return getMappedOperatorName(name.slowToString()); | |
| 176 | |
| 153 LibraryElement library = element.getLibrary(); | 177 LibraryElement library = element.getLibrary(); |
| 154 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 178 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { |
| 155 ConstructorBodyElement bodyElement = element; | 179 ConstructorBodyElement bodyElement = element; |
| 156 name = bodyElement.constructor.name; | 180 name = bodyElement.constructor.name; |
| 157 } | 181 } |
| 158 FunctionSignature signature = element.computeSignature(compiler); | 182 FunctionSignature signature = element.computeSignature(compiler); |
| 159 String methodName = | 183 String methodName = |
| 160 '${privateName(library, name)}\$${signature.parameterCount}'; | 184 '${privateName(library, name)}\$${signature.parameterCount}'; |
| 161 if (signature.optionalParametersAreNamed && | 185 if (signature.optionalParametersAreNamed && |
| 162 !signature.optionalParameters.isEmpty) { | 186 !signature.optionalParameters.isEmpty) { |
| 163 StringBuffer buffer = new StringBuffer(); | 187 StringBuffer buffer = new StringBuffer(); |
| 164 signature.orderedOptionalParameters.forEach((Element element) { | 188 signature.orderedOptionalParameters.forEach((Element element) { |
| 165 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); | 189 buffer.add('\$${safeName(element.name.slowToString())}'); |
| 166 }); | 190 }); |
| 167 methodName = '$methodName$buffer'; | 191 methodName = '$methodName$buffer'; |
| 168 } | 192 } |
| 169 if (name == closureInvocationSelectorName) return methodName; | 193 if (name == closureInvocationSelectorName) return methodName; |
| 170 return getMappedInstanceName(methodName); | 194 return getMappedInstanceName(methodName); |
| 171 } | 195 } |
| 172 | 196 |
| 173 String publicInstanceMethodNameByArity(SourceString name, int arity) { | 197 String publicInstanceMethodNameByArity(SourceString name, int arity) { |
| 174 name = Elements.operatorNameToIdentifier(name); | 198 SourceString newName = operatorNameToIdentifier(name); |
| 199 if (newName != name) return getMappedOperatorName(newName.slowToString()); | |
| 175 assert(!name.isPrivate()); | 200 assert(!name.isPrivate()); |
| 176 var base = name.slowToString(); | 201 var base = name.slowToString(); |
| 177 // We don't mangle the closure invoking function name because it | 202 // We don't mangle the closure invoking function name because it |
| 178 // is generated by string concatenation in applyFunction from | 203 // is generated by string concatenation in applyFunction from |
| 179 // js_helper.dart. | 204 // js_helper.dart. |
| 180 var proposedName = '$base\$$arity'; | 205 var proposedName = '$base\$$arity'; |
| 181 if (name == closureInvocationSelectorName) return proposedName; | 206 if (name == closureInvocationSelectorName) return proposedName; |
| 182 return getMappedInstanceName(proposedName); | 207 return getMappedInstanceName(proposedName); |
| 183 } | 208 } |
| 184 | 209 |
| 185 String invocationName(Selector selector) { | 210 String invocationName(Selector selector) { |
| 186 if (selector.isGetter()) { | 211 if (selector.isGetter()) { |
| 187 String proposedName = privateName(selector.library, selector.name); | 212 String proposedName = privateName(selector.library, selector.name); |
| 188 return 'get\$${getMappedInstanceName(proposedName)}'; | 213 return 'get\$${getMappedInstanceName(proposedName)}'; |
| 189 } else if (selector.isSetter()) { | 214 } else if (selector.isSetter()) { |
| 190 String proposedName = privateName(selector.library, selector.name); | 215 String proposedName = privateName(selector.library, selector.name); |
| 191 return 'set\$${getMappedInstanceName(proposedName)}'; | 216 return 'set\$${getMappedInstanceName(proposedName)}'; |
| 192 } else { | 217 } else { |
| 193 SourceString name = Elements.operatorNameToIdentifier(selector.name); | 218 SourceString name = selector.name; |
| 219 if (selector.kind == SelectorKind.OPERATOR | |
| 220 || selector.kind == SelectorKind.INDEX) { | |
| 221 name = operatorNameToIdentifier(name); | |
| 222 assert(name != selector.name); | |
| 223 return getMappedOperatorName(name.slowToString()); | |
| 224 } | |
| 225 assert(name == operatorNameToIdentifier(name)); | |
| 194 StringBuffer buffer = new StringBuffer(); | 226 StringBuffer buffer = new StringBuffer(); |
| 195 for (SourceString argumentName in selector.getOrderedNamedArguments()) { | 227 for (SourceString argumentName in selector.getOrderedNamedArguments()) { |
| 196 buffer.add(r'$'); | 228 buffer.add(r'$'); |
| 197 argumentName.printOn(buffer); | 229 argumentName.printOn(buffer); |
| 198 } | 230 } |
| 199 String suffix = '\$${selector.argumentCount}$buffer'; | 231 String suffix = '\$${selector.argumentCount}$buffer'; |
| 200 // We don't mangle the closure invoking function name because it | 232 // We don't mangle the closure invoking function name because it |
| 201 // is generated by string concatenation in applyFunction from | 233 // is generated by string concatenation in applyFunction from |
| 202 // js_helper.dart. | 234 // js_helper.dart. |
| 203 if (selector.isCall() && name == closureInvocationSelectorName) { | 235 if (selector.isClosureCall()) { |
| 204 return "${name.slowToString()}$suffix"; | 236 return "${name.slowToString()}$suffix"; |
| 237 } else { | |
| 238 String proposedName = privateName(selector.library, name); | |
| 239 return getMappedInstanceName('$proposedName$suffix'); | |
| 205 } | 240 } |
| 206 String proposedName = privateName(selector.library, name); | |
| 207 return getMappedInstanceName('$proposedName$suffix'); | |
| 208 } | 241 } |
| 209 } | 242 } |
| 210 | 243 |
| 211 /** | 244 /** |
| 212 * Returns the internal name used for an invocation mirror of this selector. | 245 * Returns the internal name used for an invocation mirror of this selector. |
| 213 */ | 246 */ |
| 214 String invocationMirrorInternalName(Selector selector) | 247 String invocationMirrorInternalName(Selector selector) |
| 215 => invocationName(selector); | 248 => invocationName(selector); |
| 216 | 249 |
| 217 String instanceFieldName(Element element) { | 250 String instanceFieldName(Element element) { |
| 218 String proposedName = privateName(element.getLibrary(), element.name); | 251 String proposedName = privateName(element.getLibrary(), element.name); |
| 219 return getMappedInstanceName(proposedName); | 252 return getMappedInstanceName(proposedName); |
| 220 } | 253 } |
| 221 | 254 |
| 222 // Construct a new name for the element based on the library and class it is | 255 // Construct a new name for the element based on the library and class it is |
| 223 // in. The name here is not important, we just need to make sure it is | 256 // in. The name here is not important, we just need to make sure it is |
| 224 // unique. If we are minifying, we actually construct the name from the | 257 // unique. If we are minifying, we actually construct the name from the |
| 225 // minified versions of the class and instance names, but the result is | 258 // minified versions of the class and instance names, but the result is |
| 226 // minified once again, so that is not visible in the end result. | 259 // minified once again, so that is not visible in the end result. |
| 227 String shadowedFieldName(Element fieldElement) { | 260 String shadowedFieldName(Element fieldElement) { |
| 228 // Check for following situation: Native field ${fieldElement.name} has | 261 // Check for following situation: Native field ${fieldElement.name} has |
| 229 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | 262 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this |
| 230 // name. We normally handle that by renaming the superclass field, but we | 263 // name. We normally handle that by renaming the superclass field, but we |
| 231 // can't do that because native fields have fixed JsNames. In practice | 264 // can't do that because native fields have fixed JavaScript names. |
| 232 // this can't happen because we can't inherit from native classes. | 265 // In practice this can't happen because we can't inherit from native |
| 266 // classes. | |
| 233 assert (!fieldElement.hasFixedBackendName()); | 267 assert (!fieldElement.hasFixedBackendName()); |
| 234 | 268 |
| 235 String libraryName = getName(fieldElement.getLibrary()); | 269 String libraryName = getName(fieldElement.getLibrary()); |
| 236 String className = getName(fieldElement.getEnclosingClass()); | 270 String className = getName(fieldElement.getEnclosingClass()); |
| 237 String instanceName = instanceFieldName(fieldElement); | 271 String instanceName = instanceFieldName(fieldElement); |
| 238 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); | 272 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); |
| 239 } | 273 } |
| 240 | 274 |
| 241 String setterName(Element element) { | 275 String setterName(Element element) { |
| 242 // We dynamically create setters from the field-name. The setter name must | 276 // We dynamically create setters from the field-name. The setter name must |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 269 // We dynamically create getters from the field-name. The getter name must | 303 // We dynamically create getters from the field-name. The getter name must |
| 270 // therefore be derived from the instance field-name. | 304 // therefore be derived from the instance field-name. |
| 271 LibraryElement library = element.getLibrary(); | 305 LibraryElement library = element.getLibrary(); |
| 272 String name = getMappedInstanceName(privateName(library, element.name)); | 306 String name = getMappedInstanceName(privateName(library, element.name)); |
| 273 return 'get\$$name'; | 307 return 'get\$$name'; |
| 274 } | 308 } |
| 275 | 309 |
| 276 String getMappedGlobalName(String proposedName) { | 310 String getMappedGlobalName(String proposedName) { |
| 277 var newName = globalNameMap[proposedName]; | 311 var newName = globalNameMap[proposedName]; |
| 278 if (newName == null) { | 312 if (newName == null) { |
| 279 newName = getFreshName(proposedName, usedGlobalNames); | 313 newName = getFreshName(proposedName, usedGlobalNames, true); |
| 280 globalNameMap[proposedName] = newName; | 314 globalNameMap[proposedName] = newName; |
| 281 } | 315 } |
| 282 return newName; | 316 return newName; |
| 283 } | 317 } |
| 284 | 318 |
| 285 String getMappedInstanceName(String proposedName) { | 319 String getMappedInstanceName(String proposedName) { |
| 286 var newName = instanceNameMap[proposedName]; | 320 var newName = instanceNameMap[proposedName]; |
| 287 if (newName == null) { | 321 if (newName == null) { |
| 288 newName = getFreshName(proposedName, usedInstanceNames); | 322 newName = getFreshName(proposedName, usedInstanceNames, true); |
| 289 instanceNameMap[proposedName] = newName; | 323 instanceNameMap[proposedName] = newName; |
| 290 } | 324 } |
| 291 return newName; | 325 return newName; |
| 292 } | 326 } |
| 293 | 327 |
| 294 String getFreshName(String proposedName, Set<String> usedNames) { | 328 String getMappedOperatorName(String proposedName) { |
| 329 var newName = operatorNameMap[proposedName]; | |
| 330 if (newName == null) { | |
| 331 newName = getFreshName(proposedName, usedInstanceNames, false); | |
| 332 operatorNameMap[proposedName] = newName; | |
| 333 } | |
| 334 return newName; | |
| 335 } | |
| 336 | |
| 337 String getFreshName(String proposedName, | |
| 338 Set<String> usedNames, | |
| 339 bool ensureSafe) { | |
| 295 var candidate; | 340 var candidate; |
| 296 proposedName = safeName(proposedName); | 341 if (ensureSafe) { |
| 342 proposedName = safeName(proposedName); | |
| 343 } | |
| 344 assert(!jsReserved.contains(proposedName)); | |
| 297 if (!usedNames.contains(proposedName)) { | 345 if (!usedNames.contains(proposedName)) { |
| 298 candidate = proposedName; | 346 candidate = proposedName; |
| 299 } else { | 347 } else { |
| 300 var counter = popularNameCounters[proposedName]; | 348 var counter = popularNameCounters[proposedName]; |
| 301 var i = counter == null ? 0 : counter; | 349 var i = counter == null ? 0 : counter; |
| 302 while (usedNames.contains("$proposedName$i")) { | 350 while (usedNames.contains("$proposedName$i")) { |
| 303 i++; | 351 i++; |
| 304 } | 352 } |
| 305 popularNameCounters[proposedName] = i + 1; | 353 popularNameCounters[proposedName] = i + 1; |
| 306 candidate = "$proposedName$i"; | 354 candidate = "$proposedName$i"; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 kind == ElementKind.LIBRARY || | 474 kind == ElementKind.LIBRARY || |
| 427 kind == ElementKind.MALFORMED_TYPE) { | 475 kind == ElementKind.MALFORMED_TYPE) { |
| 428 bool fixedName = false; | 476 bool fixedName = false; |
| 429 if (kind == ElementKind.CLASS) { | 477 if (kind == ElementKind.CLASS) { |
| 430 ClassElement classElement = element; | 478 ClassElement classElement = element; |
| 431 } | 479 } |
| 432 if (Elements.isInstanceField(element)) { | 480 if (Elements.isInstanceField(element)) { |
| 433 fixedName = element.hasFixedBackendName(); | 481 fixedName = element.hasFixedBackendName(); |
| 434 } | 482 } |
| 435 String result = | 483 String result = |
| 436 fixedName ? guess : getFreshName(guess, usedGlobalNames); | 484 fixedName ? guess : getFreshName(guess, usedGlobalNames, true); |
| 437 globals[element] = result; | 485 globals[element] = result; |
| 438 return result; | 486 return result; |
| 439 } | 487 } |
| 440 compiler.internalError('getName for unknown kind: ${element.kind}', | 488 compiler.internalError('getName for unknown kind: ${element.kind}', |
| 441 node: element.parseNode(compiler)); | 489 node: element.parseNode(compiler)); |
| 442 } | 490 } |
| 443 } | 491 } |
| 444 | 492 |
| 445 String getLazyInitializerName(Element element) { | 493 String getLazyInitializerName(Element element) { |
| 446 assert(Elements.isStaticOrTopLevelField(element)); | 494 assert(Elements.isStaticOrTopLevelField(element)); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 457 | 505 |
| 458 String isolateBailoutAccess(Element element) { | 506 String isolateBailoutAccess(Element element) { |
| 459 String newName = getMappedGlobalName('${getName(element)}\$bailout'); | 507 String newName = getMappedGlobalName('${getName(element)}\$bailout'); |
| 460 return '$CURRENT_ISOLATE.$newName'; | 508 return '$CURRENT_ISOLATE.$newName'; |
| 461 } | 509 } |
| 462 | 510 |
| 463 String isolateLazyInitializerAccess(Element element) { | 511 String isolateLazyInitializerAccess(Element element) { |
| 464 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; | 512 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; |
| 465 } | 513 } |
| 466 | 514 |
| 515 String operatorIsPrefix() => r'$is'; | |
| 516 | |
| 467 String operatorIs(Element element) { | 517 String operatorIs(Element element) { |
| 468 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. | 518 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. |
| 469 return 'is\$${getName(element)}'; | 519 return '${operatorIsPrefix()}${getName(element)}'; |
| 470 } | 520 } |
| 471 | 521 |
| 522 /* | |
| 523 * Returns a name that does not clash with reserved JS keywords, | |
| 524 * and also ensures it won't clash with other identifiers. | |
| 525 */ | |
| 472 String safeName(String name) { | 526 String safeName(String name) { |
| 473 if (jsReserved.contains(name) || name.startsWith('\$')) { | 527 if (jsReserved.contains(name) || name.startsWith(r'$')) { |
| 474 name = "\$$name"; | 528 name = '\$$name'; |
| 475 assert(!jsReserved.contains(name)); | |
| 476 } | 529 } |
| 530 assert(!jsReserved.contains(name)); | |
| 477 return name; | 531 return name; |
| 478 } | 532 } |
| 533 | |
| 534 SourceString operatorNameToIdentifier(SourceString name) { | |
| 535 if (name == null) return null; | |
| 536 String value = name.stringValue; | |
| 537 if (value == null) { | |
| 538 return name; | |
| 539 } else if (identical(value, '==')) { | |
| 540 return const SourceString(r'$eq'); | |
| 541 } else if (identical(value, '~')) { | |
| 542 return const SourceString(r'$not'); | |
| 543 } else if (identical(value, '[]')) { | |
| 544 return const SourceString(r'$index'); | |
| 545 } else if (identical(value, '[]=')) { | |
| 546 return const SourceString(r'$indexSet'); | |
| 547 } else if (identical(value, '*')) { | |
| 548 return const SourceString(r'$mul'); | |
| 549 } else if (identical(value, '/')) { | |
| 550 return const SourceString(r'$div'); | |
| 551 } else if (identical(value, '%')) { | |
| 552 return const SourceString(r'$mod'); | |
| 553 } else if (identical(value, '~/')) { | |
| 554 return const SourceString(r'$tdiv'); | |
| 555 } else if (identical(value, '+')) { | |
| 556 return const SourceString(r'$add'); | |
| 557 } else if (identical(value, '<<')) { | |
| 558 return const SourceString(r'$shl'); | |
| 559 } else if (identical(value, '>>')) { | |
| 560 return const SourceString(r'$shr'); | |
| 561 } else if (identical(value, '>=')) { | |
| 562 return const SourceString(r'$ge'); | |
| 563 } else if (identical(value, '>')) { | |
| 564 return const SourceString(r'$gt'); | |
| 565 } else if (identical(value, '<=')) { | |
| 566 return const SourceString(r'$le'); | |
| 567 } else if (identical(value, '<')) { | |
| 568 return const SourceString(r'$lt'); | |
| 569 } else if (identical(value, '&')) { | |
| 570 return const SourceString(r'$and'); | |
| 571 } else if (identical(value, '^')) { | |
| 572 return const SourceString(r'$xor'); | |
| 573 } else if (identical(value, '|')) { | |
| 574 return const SourceString(r'$or'); | |
| 575 } else if (identical(value, '-')) { | |
| 576 return const SourceString(r'$sub'); | |
| 577 } else if (identical(value, 'unary-')) { | |
| 578 return const SourceString(r'$negate'); | |
| 579 } else { | |
| 580 return name; | |
| 581 } | |
| 582 } | |
| 479 } | 583 } |
| OLD | NEW |