| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 final String metadataField = '@'; | 219 final String metadataField = '@'; |
| 220 final String callCatchAllName = r'call$catchAll'; | 220 final String callCatchAllName = r'call$catchAll'; |
| 221 final String reflectableField = r'$reflectable'; | 221 final String reflectableField = r'$reflectable'; |
| 222 final String defaultValuesField = r'$defaultValues'; | 222 final String defaultValuesField = r'$defaultValues'; |
| 223 final String methodsWithOptionalArgumentsField = | 223 final String methodsWithOptionalArgumentsField = |
| 224 r'$methodsWithOptionalArguments'; | 224 r'$methodsWithOptionalArguments'; |
| 225 | 225 |
| 226 // Name of property in a class description for the native dispatch metadata. | 226 // Name of property in a class description for the native dispatch metadata. |
| 227 final String nativeSpecProperty = '%'; | 227 final String nativeSpecProperty = '%'; |
| 228 | 228 |
| 229 static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$'); |
| 230 static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]'); |
| 231 |
| 229 /** | 232 /** |
| 230 * Map from top-level or static elements to their unique identifiers provided | 233 * Map from top-level or static elements to their unique identifiers provided |
| 231 * by [getName]. | 234 * by [getName]. |
| 232 * | 235 * |
| 233 * Invariant: Keys must be declaration elements. | 236 * Invariant: Keys must be declaration elements. |
| 234 */ | 237 */ |
| 235 final Compiler compiler; | 238 final Compiler compiler; |
| 236 final Map<Element, String> globals; | 239 final Map<Element, String> globals; |
| 237 final Map<String, LibraryElement> shortPrivateNameOwners; | 240 final Map<String, LibraryElement> shortPrivateNameOwners; |
| 238 | 241 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } | 436 } |
| 434 } | 437 } |
| 435 } | 438 } |
| 436 | 439 |
| 437 /** | 440 /** |
| 438 * Returns the internal name used for an invocation mirror of this selector. | 441 * Returns the internal name used for an invocation mirror of this selector. |
| 439 */ | 442 */ |
| 440 String invocationMirrorInternalName(Selector selector) | 443 String invocationMirrorInternalName(Selector selector) |
| 441 => invocationName(selector); | 444 => invocationName(selector); |
| 442 | 445 |
| 443 String instanceFieldName(Element element) { | 446 /** |
| 447 * Returns name of accessor (root to getter and setter) for a static or |
| 448 * instance field. |
| 449 */ |
| 450 String fieldAccessorName(Element element) { |
| 451 return element.isInstanceMember() |
| 452 ? instanceFieldAccessorName(element) |
| 453 : getNameOfField(element); |
| 454 } |
| 455 |
| 456 /** |
| 457 * Returns name of the JavaScript property used to store a static or instance |
| 458 * field. |
| 459 */ |
| 460 String fieldPropertyName(Element element) { |
| 461 return element.isInstanceMember() |
| 462 ? instanceFieldPropertyName(element) |
| 463 : getNameOfField(element); |
| 464 } |
| 465 |
| 466 /** |
| 467 * Returns name of accessor (root to getter and setter) for an instance field. |
| 468 */ |
| 469 String instanceFieldAccessorName(Element element) { |
| 444 String proposedName = privateName(element.getLibrary(), element.name); | 470 String proposedName = privateName(element.getLibrary(), element.name); |
| 445 return getMappedInstanceName(proposedName); | 471 return getMappedInstanceName(proposedName); |
| 446 } | 472 } |
| 447 | 473 |
| 448 // Construct a new name for the element based on the library and class it is | 474 /** |
| 449 // in. The name here is not important, we just need to make sure it is | 475 * Returns name of the JavaScript property used to store an instance field. |
| 450 // unique. If we are minifying, we actually construct the name from the | 476 */ |
| 451 // minified versions of the class and instance names, but the result is | 477 String instanceFieldPropertyName(Element element) { |
| 452 // minified once again, so that is not visible in the end result. | 478 if (element.hasFixedBackendName()) { |
| 453 String shadowedFieldName(Element fieldElement) { | 479 return element.fixedBackendName(); |
| 454 // Check for following situation: Native field ${fieldElement.name} has | 480 } |
| 455 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this | 481 // If a class is used anywhere as a mixin, we must make the name unique so |
| 456 // name. We normally handle that by renaming the superclass field, but we | 482 // that it does not accidentally shadow. Also, the mixin name must be |
| 457 // can't do that because native fields have fixed JavaScript names. | 483 // constant over all mixins. |
| 458 // In practice this can't happen because we can't inherit from native | 484 if (compiler.world.isUsedAsMixin(element.getEnclosingClass()) || |
| 459 // classes. | 485 shadowingAnotherField(element)) { |
| 460 assert (!fieldElement.hasFixedBackendName()); | 486 // Construct a new name for the element based on the library and class it |
| 487 // is in. The name here is not important, we just need to make sure it is |
| 488 // unique. If we are minifying, we actually construct the name from the |
| 489 // minified version of the class name, but the result is minified once |
| 490 // again, so that is not visible in the end result. |
| 491 String libraryName = getNameOfLibrary(element.getLibrary()); |
| 492 String className = getNameOfClass(element.getEnclosingClass()); |
| 493 String instanceName = privateName(element.getLibrary(), element.name); |
| 494 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); |
| 495 } |
| 461 | 496 |
| 462 String libraryName = getNameOfLibrary(fieldElement.getLibrary()); | 497 String proposedName = privateName(element.getLibrary(), element.name); |
| 463 String className = getNameOfClass(fieldElement.getEnclosingClass()); | 498 return getMappedInstanceName(proposedName); |
| 464 String instanceName = instanceFieldName(fieldElement); | 499 } |
| 465 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); | 500 |
| 501 |
| 502 bool shadowingAnotherField(Element element) { |
| 503 return element.getEnclosingClass().hasFieldShadowedBy(element); |
| 466 } | 504 } |
| 467 | 505 |
| 468 String setterName(Element element) { | 506 String setterName(Element element) { |
| 469 // We dynamically create setters from the field-name. The setter name must | 507 // We dynamically create setters from the field-name. The setter name must |
| 470 // therefore be derived from the instance field-name. | 508 // therefore be derived from the instance field-name. |
| 471 LibraryElement library = element.getLibrary(); | 509 LibraryElement library = element.getLibrary(); |
| 472 String name = getMappedInstanceName(privateName(library, element.name)); | 510 String name = getMappedInstanceName(privateName(library, element.name)); |
| 473 return '$setterPrefix$name'; | 511 return '$setterPrefix$name'; |
| 474 } | 512 } |
| 475 | 513 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 LibraryElement library = element; | 623 LibraryElement library = element; |
| 586 name = library.getLibraryOrScriptName(); | 624 name = library.getLibraryOrScriptName(); |
| 587 if (name.contains('.')) { | 625 if (name.contains('.')) { |
| 588 // For libraries that have a library tag, we use the last part | 626 // For libraries that have a library tag, we use the last part |
| 589 // of the fully qualified name as their base name. For all other | 627 // of the fully qualified name as their base name. For all other |
| 590 // libraries, we use the first part of their filename. | 628 // libraries, we use the first part of their filename. |
| 591 name = library.hasLibraryName() | 629 name = library.hasLibraryName() |
| 592 ? name.substring(name.lastIndexOf('.') + 1) | 630 ? name.substring(name.lastIndexOf('.') + 1) |
| 593 : name.substring(0, name.indexOf('.')); | 631 : name.substring(0, name.indexOf('.')); |
| 594 } | 632 } |
| 633 // The filename based name can contain all kinds of nasty characters. Make |
| 634 // sure it is an identifier. |
| 635 if (!IDENTIFIER.hasMatch(name)) { |
| 636 name = name.replaceAllMapped(NON_IDENTIFIER_CHAR, |
| 637 (match) => match[0].codeUnitAt(0).toRadixString(16)); |
| 638 if (!IDENTIFIER.hasMatch(name)) { // e.g. starts with digit. |
| 639 name = 'lib_$name'; |
| 640 } |
| 641 } |
| 595 } else { | 642 } else { |
| 596 name = element.name; | 643 name = element.name; |
| 597 } | 644 } |
| 598 return name; | 645 return name; |
| 599 } | 646 } |
| 600 | 647 |
| 601 String getInterceptorSuffix(Iterable<ClassElement> classes) { | 648 String getInterceptorSuffix(Iterable<ClassElement> classes) { |
| 602 String abbreviate(ClassElement cls) { | 649 String abbreviate(ClassElement cls) { |
| 603 if (cls == compiler.objectClass) return "o"; | 650 if (cls == compiler.objectClass) return "o"; |
| 604 JavaScriptBackend backend = compiler.backend; | 651 JavaScriptBackend backend = compiler.backend; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 String getNameX(Element element) { | 758 String getNameX(Element element) { |
| 712 if (element.isInstanceMember()) { | 759 if (element.isInstanceMember()) { |
| 713 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 760 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 714 || element.kind == ElementKind.FUNCTION) { | 761 || element.kind == ElementKind.FUNCTION) { |
| 715 return instanceMethodName(element); | 762 return instanceMethodName(element); |
| 716 } else if (element.kind == ElementKind.GETTER) { | 763 } else if (element.kind == ElementKind.GETTER) { |
| 717 return getterName(element); | 764 return getterName(element); |
| 718 } else if (element.kind == ElementKind.SETTER) { | 765 } else if (element.kind == ElementKind.SETTER) { |
| 719 return setterName(element); | 766 return setterName(element); |
| 720 } else if (element.kind == ElementKind.FIELD) { | 767 } else if (element.kind == ElementKind.FIELD) { |
| 721 return instanceFieldName(element); | 768 compiler.internalError( |
| 769 'use instanceFieldPropertyName or instanceFieldAccessorName', |
| 770 node: element.parseNode(compiler)); |
| 722 } else { | 771 } else { |
| 723 compiler.internalError('getName for bad kind: ${element.kind}', | 772 compiler.internalError('getName for bad kind: ${element.kind}', |
| 724 node: element.parseNode(compiler)); | 773 node: element.parseNode(compiler)); |
| 725 } | 774 } |
| 726 } else { | 775 } else { |
| 727 // Use declaration element to ensure invariant on [globals]. | 776 // Use declaration element to ensure invariant on [globals]. |
| 728 element = element.declaration; | 777 element = element.declaration; |
| 729 // Dealing with a top-level or static element. | 778 // Dealing with a top-level or static element. |
| 730 String cached = globals[element]; | 779 String cached = globals[element]; |
| 731 if (cached != null) return cached; | 780 if (cached != null) return cached; |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 if (!first) { | 1387 if (!first) { |
| 1339 sb.write('_'); | 1388 sb.write('_'); |
| 1340 } | 1389 } |
| 1341 sb.write('_'); | 1390 sb.write('_'); |
| 1342 visit(link.head); | 1391 visit(link.head); |
| 1343 first = true; | 1392 first = true; |
| 1344 } | 1393 } |
| 1345 } | 1394 } |
| 1346 } | 1395 } |
| 1347 } | 1396 } |
| OLD | NEW |