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 { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 } | 92 } |
| 93 } else { | 93 } else { |
| 94 longName = "CONSTANT"; | 94 longName = "CONSTANT"; |
| 95 } | 95 } |
| 96 result = getFreshName(longName, usedGlobalNames); | 96 result = getFreshName(longName, usedGlobalNames); |
| 97 constantNames[constant] = result; | 97 constantNames[constant] = result; |
| 98 } | 98 } |
| 99 return result; | 99 return result; |
| 100 } | 100 } |
| 101 | 101 |
| 102 String closureInvocationName(Selector selector) { | |
| 103 return instanceMethodInvocationName(null, closureInvocationSelectorName, | |
| 104 selector); | |
| 105 } | |
| 106 | |
| 107 String breakLabelName(LabelElement label) { | 102 String breakLabelName(LabelElement label) { |
| 108 return '\$${label.labelName}\$${label.target.nestingLevel}'; | 103 return '\$${label.labelName}\$${label.target.nestingLevel}'; |
| 109 } | 104 } |
| 110 | 105 |
| 111 String implicitBreakLabelName(TargetElement target) { | 106 String implicitBreakLabelName(TargetElement target) { |
| 112 return '\$${target.nestingLevel}'; | 107 return '\$${target.nestingLevel}'; |
| 113 } | 108 } |
| 114 | 109 |
| 115 // We sometimes handle continue targets differently from break targets, | 110 // We sometimes handle continue targets differently from break targets, |
| 116 // so we have special continue-only labels. | 111 // so we have special continue-only labels. |
| 117 String continueLabelName(LabelElement label) { | 112 String continueLabelName(LabelElement label) { |
| 118 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; | 113 return 'c\$${label.labelName}\$${label.target.nestingLevel}'; |
| 119 } | 114 } |
| 120 | 115 |
| 121 String implicitContinueLabelName(TargetElement target) { | 116 String implicitContinueLabelName(TargetElement target) { |
| 122 return 'c\$${target.nestingLevel}'; | 117 return 'c\$${target.nestingLevel}'; |
| 123 } | 118 } |
| 124 | 119 |
| 125 /** | 120 /** |
| 126 * If the [name] is not private returns [:name.slowToString():]. Otherwise | 121 * If the [name] is not private returns [:name.slowToString():]. Otherwise |
| 127 * mangles the [name] so that each library has a unique name. | 122 * mangles the [name] so that each library has a unique name. |
| 128 */ | 123 */ |
| 129 String privateName(LibraryElement lib, SourceString name) { | 124 String privateName(LibraryElement library, SourceString name) { |
| 130 String result; | 125 // Public names are easy. |
| 131 if (name.isPrivate()) { | 126 String nameString = name.slowToString(); |
| 132 String nameString = name.slowToString(); | 127 if (!name.isPrivate()) return nameString; |
| 133 // The first library asking for a short private name wins. | 128 |
| 134 LibraryElement owner = shouldMinify ? | 129 // The first library asking for a short private name wins. |
| 135 lib : | 130 LibraryElement owner = shouldMinify |
| 136 shortPrivateNameOwners.putIfAbsent(nameString, () => lib); | 131 ? library |
| 137 // If a private name could clash with a mangled private name we don't | 132 : shortPrivateNameOwners.putIfAbsent(nameString, () => library); |
| 138 // use the short name. For example a private name "_lib3_foo" would | 133 |
| 139 // clash with "_foo" from "lib3". | 134 // If a private name could clash with a mangled private name we don't |
| 140 if (owner == lib && | 135 // use the short name. For example a private name "_lib3_foo" would |
| 141 !nameString.startsWith('_$LIBRARY_PREFIX') && | 136 // clash with "_foo" from "lib3". |
| 142 !shouldMinify) { | 137 if (owner == library && |
| 143 result = nameString; | 138 !nameString.startsWith('_$LIBRARY_PREFIX') && |
| 144 } else { | 139 !shouldMinify) { |
| 145 String libName = getName(lib); | 140 return nameString; |
| 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 } | |
| 152 } else { | |
| 153 result = name.slowToString(); | |
| 154 } | 141 } |
| 155 return result; | 142 |
| 143 // If a library name does not start with the [LIBRARY_PREFIX] then our | |
| 144 // assumptions about clashing with mangled private members do not hold. | |
| 145 String libraryName = getName(library); | |
| 146 assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX)); | |
| 147 // TODO(erikcorry): Fix this with other manglings to avoid clashes. | |
| 148 return '_library$libraryName\$$nameString'; | |
|
ngeoffray
2013/01/11 10:29:11
Note that you just changed the name to start with
| |
| 156 } | 149 } |
| 157 | 150 |
| 158 String instanceMethodName(FunctionElement element) { | 151 String instanceMethodName(FunctionElement element) { |
| 159 SourceString name = Elements.operatorNameToIdentifier(element.name); | 152 SourceString name = Elements.operatorNameToIdentifier(element.name); |
| 160 LibraryElement lib = element.getLibrary(); | 153 LibraryElement library = element.getLibrary(); |
| 161 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 154 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { |
| 162 ConstructorBodyElement bodyElement = element; | 155 ConstructorBodyElement bodyElement = element; |
| 163 name = bodyElement.constructor.name; | 156 name = bodyElement.constructor.name; |
| 164 } | 157 } |
| 165 FunctionSignature signature = element.computeSignature(compiler); | 158 FunctionSignature signature = element.computeSignature(compiler); |
| 166 String methodName = | 159 String methodName = |
| 167 '${privateName(lib, name)}\$${signature.parameterCount}'; | 160 '${privateName(library, name)}\$${signature.parameterCount}'; |
| 168 if (signature.optionalParametersAreNamed && | 161 if (signature.optionalParametersAreNamed && |
| 169 !signature.optionalParameters.isEmpty) { | 162 !signature.optionalParameters.isEmpty) { |
| 170 StringBuffer buffer = new StringBuffer(); | 163 StringBuffer buffer = new StringBuffer(); |
| 171 signature.orderedOptionalParameters.forEach((Element element) { | 164 signature.orderedOptionalParameters.forEach((Element element) { |
| 172 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); | 165 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); |
| 173 }); | 166 }); |
| 174 methodName = '$methodName$buffer'; | 167 methodName = '$methodName$buffer'; |
| 175 } | 168 } |
| 176 if (name == closureInvocationSelectorName) return methodName; | 169 if (name == closureInvocationSelectorName) return methodName; |
| 177 return getMappedInstanceName(methodName); | 170 return getMappedInstanceName(methodName); |
| 178 } | 171 } |
| 179 | 172 |
| 180 String publicInstanceMethodNameByArity(SourceString name, int arity) { | 173 String publicInstanceMethodNameByArity(SourceString name, int arity) { |
| 181 name = Elements.operatorNameToIdentifier(name); | 174 name = Elements.operatorNameToIdentifier(name); |
| 182 assert(!name.isPrivate()); | 175 assert(!name.isPrivate()); |
| 183 var base = name.slowToString(); | 176 var base = name.slowToString(); |
| 184 // We don't mangle the closure invoking function name because it is | 177 // We don't mangle the closure invoking function name because it is |
| 185 // generated in by string concatenation applyFunction from js_helper.dart. | 178 // generated in by string concatenation applyFunction from js_helper.dart. |
| 186 var proposedName = '$base\$$arity'; | 179 var proposedName = '$base\$$arity'; |
| 187 if (base == closureInvocationSelectorName) return proposedName; | 180 if (base == closureInvocationSelectorName) return proposedName; |
| 188 return getMappedInstanceName(proposedName); | 181 return getMappedInstanceName(proposedName); |
| 189 } | 182 } |
| 190 | 183 |
| 191 String instanceMethodInvocationName(LibraryElement lib, SourceString name, | 184 String invocationName(Selector selector) { |
| 192 Selector selector) { | 185 if (selector.isGetter()) { |
| 193 name = Elements.operatorNameToIdentifier(name); | 186 String proposedName = privateName(selector.library, selector.name); |
| 194 // TODO(floitsch): mangle, while preserving uniqueness. | 187 return 'get\$${getMappedInstanceName(proposedName)}'; |
| 195 StringBuffer buffer = new StringBuffer(); | 188 } else if (selector.isSetter()) { |
| 196 List<SourceString> names = selector.getOrderedNamedArguments(); | 189 String proposedName = privateName(selector.library, selector.name); |
| 197 for (SourceString argumentName in names) { | 190 return 'set\$${getMappedInstanceName(proposedName)}'; |
| 198 buffer.add(r'$'); | 191 } else { |
| 199 argumentName.printOn(buffer); | 192 assert(selector.isCall()); |
| 193 SourceString name = Elements.operatorNameToIdentifier(selector.name); | |
| 194 StringBuffer buffer = new StringBuffer(); | |
| 195 for (SourceString argumentName in selector.getOrderedNamedArguments()) { | |
| 196 buffer.add(r'$'); | |
| 197 argumentName.printOn(buffer); | |
| 198 } | |
| 199 String suffix = '\$${selector.argumentCount}$buffer'; | |
| 200 // We don't mangle the closure invoking function name because it | |
| 201 // is generated in by string concatenation applyFunction from | |
|
ngeoffray
2013/01/11 10:29:11
in by string concatenation applyFunction -> by str
| |
| 202 // js_helper.dart. | |
| 203 if (selector.isClosureCall()) return "$name$suffix"; | |
| 204 String proposedName = privateName(selector.library, name); | |
| 205 return getMappedInstanceName('$proposedName$suffix'); | |
| 200 } | 206 } |
| 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'); | |
| 208 } | 207 } |
| 209 | 208 |
| 210 /** | 209 /** |
| 211 * Returns the internal name used for an invocation mirror of this selector. | 210 * Returns the internal name used for an invocation mirror of this selector. |
| 212 */ | 211 */ |
| 213 String invocationMirrorInternalName(Selector selector) { | 212 String invocationMirrorInternalName(Selector selector) |
| 214 if (selector.isGetter()) { | 213 => invocationName(selector); |
| 215 return getterName(selector.library, selector.name); | |
| 216 } else if (selector.isSetter()) { | |
| 217 return setterName(selector.library, selector.name); | |
| 218 } else { | |
| 219 return instanceMethodInvocationName( | |
| 220 selector.library, selector.name, selector); | |
| 221 } | |
| 222 } | |
| 223 | 214 |
| 224 String instanceFieldName(LibraryElement libraryElement, SourceString name) { | 215 String instanceFieldName(Element element) { |
| 225 String proposedName = privateName(libraryElement, name); | 216 String proposedName = privateName(element.getLibrary(), element.name); |
| 226 return getMappedInstanceName(proposedName); | 217 return getMappedInstanceName(proposedName); |
| 227 } | 218 } |
| 228 | 219 |
| 229 // Construct a new name for the element based on the library and class it is | 220 // Construct a new name for the element based on the library and class it is |
| 230 // in. The name here is not important, we just need to make sure it is | 221 // in. The name here is not important, we just need to make sure it is |
| 231 // unique. If we are minifying, we actually construct the name from the | 222 // unique. If we are minifying, we actually construct the name from the |
| 232 // minified versions of the class and instance names, but the result is | 223 // minified versions of the class and instance names, but the result is |
| 233 // minified once again, so that is not visible in the end result. | 224 // minified once again, so that is not visible in the end result. |
| 234 String shadowedFieldName(Element fieldElement) { | 225 String shadowedFieldName(Element fieldElement) { |
| 235 // Check for following situation: Native field ${fieldElement.name} has | 226 // Check for following situation: Native field ${fieldElement.name} has |
| 236 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | 227 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this |
| 237 // name. We normally handle that by renaming the superclass field, but we | 228 // name. We normally handle that by renaming the superclass field, but we |
| 238 // can't do that because native fields have fixed JsNames. In practice | 229 // can't do that because native fields have fixed JsNames. In practice |
| 239 // this can't happen because we can't inherit from native classes. | 230 // this can't happen because we can't inherit from native classes. |
| 240 assert (!fieldElement.hasFixedBackendName()); | 231 assert (!fieldElement.hasFixedBackendName()); |
| 241 | 232 |
| 242 ClassElement cls = fieldElement.getEnclosingClass(); | 233 String libraryName = getName(fieldElement.getLibrary()); |
| 243 LibraryElement libraryElement = fieldElement.getLibrary(); | 234 String className = getName(fieldElement.getEnclosingClass()); |
| 244 String libName = getName(libraryElement); | 235 String instanceName = instanceFieldName(fieldElement); |
| 245 String clsName = getName(cls); | 236 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); |
| 246 String instanceName = instanceFieldName(libraryElement, fieldElement.name); | |
| 247 return getMappedInstanceName('$libName\$$clsName\$$instanceName'); | |
| 248 } | 237 } |
| 249 | 238 |
| 250 String setterName(LibraryElement lib, SourceString name) { | 239 String setterName(Element element) { |
| 251 // We dynamically create setters from the field-name. The setter name must | 240 // We dynamically create setters from the field-name. The setter name must |
| 252 // therefore be derived from the instance field-name. | 241 // therefore be derived from the instance field-name. |
| 253 String fieldName = getMappedInstanceName(privateName(lib, name)); | 242 LibraryElement library = element.getLibrary(); |
| 254 return 'set\$$fieldName'; | 243 String name = getMappedInstanceName(privateName(library, element.name)); |
| 244 return 'set\$$name'; | |
| 255 } | 245 } |
| 256 | 246 |
| 257 String setterNameFromAccessorName(String name) { | 247 String setterNameFromAccessorName(String name) { |
| 258 // We dynamically create setters from the field-name. The setter name must | 248 // We dynamically create setters from the field-name. The setter name must |
| 259 // therefore be derived from the instance field-name. | 249 // therefore be derived from the instance field-name. |
| 260 return 'set\$$name'; | 250 return 'set\$$name'; |
| 261 } | 251 } |
| 262 | 252 |
| 263 String publicGetterName(SourceString name) { | 253 String publicGetterName(SourceString name) { |
| 264 // We dynamically create getters from the field-name. The getter name must | 254 // We dynamically create getters from the field-name. The getter name must |
| 265 // therefore be derived from the instance field-name. | 255 // therefore be derived from the instance field-name. |
| 266 String fieldName = getMappedInstanceName(name.slowToString()); | 256 String fieldName = getMappedInstanceName(name.slowToString()); |
| 267 return 'get\$$fieldName'; | 257 return 'get\$$fieldName'; |
| 268 } | 258 } |
| 269 | 259 |
| 270 String getterNameFromAccessorName(String name) { | 260 String getterNameFromAccessorName(String name) { |
| 271 // We dynamically create getters from the field-name. The getter name must | 261 // We dynamically create getters from the field-name. The getter name must |
| 272 // therefore be derived from the instance field-name. | 262 // therefore be derived from the instance field-name. |
| 273 return 'get\$$name'; | 263 return 'get\$$name'; |
| 274 } | 264 } |
| 275 | 265 |
| 276 String getterName(LibraryElement lib, SourceString name) { | 266 String getterName(Element element) { |
| 277 // We dynamically create getters from the field-name. The getter name must | 267 // We dynamically create getters from the field-name. The getter name must |
| 278 // therefore be derived from the instance field-name. | 268 // therefore be derived from the instance field-name. |
| 279 String fieldName = getMappedInstanceName(privateName(lib, name)); | 269 LibraryElement library = element.getLibrary(); |
| 280 return 'get\$$fieldName'; | 270 String name = getMappedInstanceName(privateName(library, element.name)); |
| 271 return 'get\$$name'; | |
| 281 } | 272 } |
| 282 | 273 |
| 283 String getMappedGlobalName(String proposedName) { | 274 String getMappedGlobalName(String proposedName) { |
| 284 var newName = globalNameMap[proposedName]; | 275 var newName = globalNameMap[proposedName]; |
| 285 if (newName == null) { | 276 if (newName == null) { |
| 286 newName = getFreshName(proposedName, usedGlobalNames); | 277 newName = getFreshName(proposedName, usedGlobalNames); |
| 287 globalNameMap[proposedName] = newName; | 278 globalNameMap[proposedName] = newName; |
| 288 } | 279 } |
| 289 return newName; | 280 return newName; |
| 290 } | 281 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 321 } | 312 } |
| 322 | 313 |
| 323 static const String LIBRARY_PREFIX = "lib"; | 314 static const String LIBRARY_PREFIX = "lib"; |
| 324 | 315 |
| 325 /** | 316 /** |
| 326 * Returns a preferred JS-id for the given top-level or static element. | 317 * Returns a preferred JS-id for the given top-level or static element. |
| 327 * The returned id is guaranteed to be a valid JS-id. | 318 * The returned id is guaranteed to be a valid JS-id. |
| 328 */ | 319 */ |
| 329 String _computeGuess(Element element) { | 320 String _computeGuess(Element element) { |
| 330 assert(!element.isInstanceMember()); | 321 assert(!element.isInstanceMember()); |
| 331 LibraryElement lib = element.getLibrary(); | |
| 332 String name; | 322 String name; |
| 333 if (element.isGenerativeConstructor()) { | 323 if (element.isGenerativeConstructor()) { |
| 334 if (element.name == element.getEnclosingClass().name) { | 324 if (element.name == element.getEnclosingClass().name) { |
| 335 // Keep the class name for the class and not the factory. | 325 // Keep the class name for the class and not the factory. |
| 336 name = "${element.name.slowToString()}\$"; | 326 name = "${element.name.slowToString()}\$"; |
| 337 } else { | 327 } else { |
| 338 name = element.name.slowToString(); | 328 name = element.name.slowToString(); |
| 339 } | 329 } |
| 340 } else if (Elements.isStaticOrTopLevel(element)) { | 330 } else if (Elements.isStaticOrTopLevel(element)) { |
| 341 if (element.isMember()) { | 331 if (element.isMember()) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 * | 384 * |
| 395 * For accessing statics consider calling | 385 * For accessing statics consider calling |
| 396 * [isolateAccess]/[isolateBailoutAccess] or [isolatePropertyAccess] instead. | 386 * [isolateAccess]/[isolateBailoutAccess] or [isolatePropertyAccess] instead. |
| 397 */ | 387 */ |
| 398 String getName(Element element) { | 388 String getName(Element element) { |
| 399 if (element.isInstanceMember()) { | 389 if (element.isInstanceMember()) { |
| 400 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 390 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 401 || element.kind == ElementKind.FUNCTION) { | 391 || element.kind == ElementKind.FUNCTION) { |
| 402 return instanceMethodName(element); | 392 return instanceMethodName(element); |
| 403 } else if (element.kind == ElementKind.GETTER) { | 393 } else if (element.kind == ElementKind.GETTER) { |
| 404 return getterName(element.getLibrary(), element.name); | 394 return getterName(element); |
| 405 } else if (element.kind == ElementKind.SETTER) { | 395 } else if (element.kind == ElementKind.SETTER) { |
| 406 return setterName(element.getLibrary(), element.name); | 396 return setterName(element); |
| 407 } else if (element.kind == ElementKind.FIELD) { | 397 } else if (element.kind == ElementKind.FIELD) { |
| 408 return instanceFieldName(element.getLibrary(), element.name); | 398 return instanceFieldName(element); |
| 409 } else { | 399 } else { |
| 410 compiler.internalError('getName for bad kind: ${element.kind}', | 400 compiler.internalError('getName for bad kind: ${element.kind}', |
| 411 node: element.parseNode(compiler)); | 401 node: element.parseNode(compiler)); |
| 412 } | 402 } |
| 413 } else { | 403 } else { |
| 414 // Use declaration element to ensure invariant on [globals]. | 404 // Use declaration element to ensure invariant on [globals]. |
| 415 element = element.declaration; | 405 element = element.declaration; |
| 416 // Dealing with a top-level or static element. | 406 // Dealing with a top-level or static element. |
| 417 String cached = globals[element]; | 407 String cached = globals[element]; |
| 418 if (cached != null) return cached; | 408 if (cached != null) return cached; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 } | 468 } |
| 479 | 469 |
| 480 String safeName(String name) { | 470 String safeName(String name) { |
| 481 if (jsReserved.contains(name) || name.startsWith('\$')) { | 471 if (jsReserved.contains(name) || name.startsWith('\$')) { |
| 482 name = "\$$name"; | 472 name = "\$$name"; |
| 483 assert(!jsReserved.contains(name)); | 473 assert(!jsReserved.contains(name)); |
| 484 } | 474 } |
| 485 return name; | 475 return name; |
| 486 } | 476 } |
| 487 } | 477 } |
| OLD | NEW |