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 * Names are generated through three stages: | 10 * Names are generated through three stages: |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 * If the [originalName] is not private returns [originalName]. Otherwise | 489 * If the [originalName] is not private returns [originalName]. Otherwise |
490 * mangles the [originalName] so that each library has its own distinguished | 490 * mangles the [originalName] so that each library has its own distinguished |
491 * version of the name. | 491 * version of the name. |
492 * | 492 * |
493 * Although the name is not guaranteed to be unique within any namespace, | 493 * Although the name is not guaranteed to be unique within any namespace, |
494 * clashes are very unlikely in practice. Therefore, it can be used in cases | 494 * clashes are very unlikely in practice. Therefore, it can be used in cases |
495 * where uniqueness is nice but not a strict requirement. | 495 * where uniqueness is nice but not a strict requirement. |
496 * | 496 * |
497 * The resulting name is a *proposed name* and is never minified. | 497 * The resulting name is a *proposed name* and is never minified. |
498 */ | 498 */ |
499 String privateName(LibraryElement library, String originalName) { | 499 String privateName(Name originalName) { |
| 500 String text = originalName.text; |
| 501 |
500 // Public names are easy. | 502 // Public names are easy. |
501 if (!isPrivateName(originalName)) return originalName; | 503 if (!originalName.isPrivate) return text; |
| 504 |
| 505 LibraryElement library = originalName.library; |
502 | 506 |
503 // The first library asking for a short private name wins. | 507 // The first library asking for a short private name wins. |
504 LibraryElement owner = | 508 LibraryElement owner = |
505 shortPrivateNameOwners.putIfAbsent(originalName, () => library); | 509 shortPrivateNameOwners.putIfAbsent(text, () => library); |
506 | 510 |
507 if (owner == library) { | 511 if (owner == library) { |
508 return originalName; | 512 return text; |
509 } else { | 513 } else { |
510 // Make sure to return a private name that starts with _ so it | 514 // Make sure to return a private name that starts with _ so it |
511 // cannot clash with any public names. | 515 // cannot clash with any public names. |
512 // The name is still not guaranteed to be unique, since both the library | 516 // The name is still not guaranteed to be unique, since both the library |
513 // name and originalName could contain $ symbols. | 517 // name and originalName could contain $ symbols. |
514 String libraryName = _disambiguateGlobal(library); | 518 String libraryName = _disambiguateGlobal(library); |
515 return '_$libraryName\$${originalName}'; | 519 return '_$libraryName\$${text}'; |
516 } | 520 } |
517 } | 521 } |
518 | 522 |
519 String _proposeNameForConstructorBody(ConstructorBodyElement method) { | 523 String _proposeNameForConstructorBody(ConstructorBodyElement method) { |
520 String name = Elements.reconstructConstructorNameSourceString(method); | 524 String name = Elements.reconstructConstructorNameSourceString(method); |
521 // We include the method suffix on constructor bodies. It has no purpose, | 525 // We include the method suffix on constructor bodies. It has no purpose, |
522 // but this way it produces the same names as previous versions of the | 526 // but this way it produces the same names as previous versions of the |
523 // Namer class did. | 527 // Namer class did. |
524 List<String> suffix = callSuffixForSignature(method.functionSignature); | 528 List<String> suffix = callSuffixForSignature(method.functionSignature); |
525 return '$name\$${suffix.join(r'$')}'; | 529 return '$name\$${suffix.join(r'$')}'; |
(...skipping 25 matching lines...) Expand all Loading... |
551 // TODO(asgerf): Avoid clashes when named parameters contain $ symbols. | 555 // TODO(asgerf): Avoid clashes when named parameters contain $ symbols. |
552 return '$callPrefix\$${suffix.join(r'$')}'; | 556 return '$callPrefix\$${suffix.join(r'$')}'; |
553 } | 557 } |
554 | 558 |
555 /// The suffix list for the pattern: | 559 /// The suffix list for the pattern: |
556 /// | 560 /// |
557 /// $<N>$namedParam1...$namedParam<M> | 561 /// $<N>$namedParam1...$namedParam<M> |
558 /// | 562 /// |
559 /// This is used for the annotated names of `call`, and for the proposed name | 563 /// This is used for the annotated names of `call`, and for the proposed name |
560 /// for other instance methods. | 564 /// for other instance methods. |
561 List<String> callSuffixForSelector(Selector selector) { | 565 List<String> callSuffixForStructure(CallStructure callStructure) { |
562 List<String> suffixes = ['${selector.argumentCount}']; | 566 List<String> suffixes = ['${callStructure.argumentCount}']; |
563 suffixes.addAll(selector.getOrderedNamedArguments()); | 567 suffixes.addAll(callStructure.getOrderedNamedArguments()); |
564 return suffixes; | 568 return suffixes; |
565 } | 569 } |
566 | 570 |
567 /// The suffix list for the pattern: | 571 /// The suffix list for the pattern: |
568 /// | 572 /// |
569 /// $<N>$namedParam1...$namedParam<M> | 573 /// $<N>$namedParam1...$namedParam<M> |
570 /// | 574 /// |
571 /// This is used for the annotated names of `call`, and for the proposed name | 575 /// This is used for the annotated names of `call`, and for the proposed name |
572 /// for other instance methods. | 576 /// for other instance methods. |
573 List<String> callSuffixForSignature(FunctionSignature sig) { | 577 List<String> callSuffixForSignature(FunctionSignature sig) { |
574 List<String> suffixes = ['${sig.parameterCount}']; | 578 List<String> suffixes = ['${sig.parameterCount}']; |
575 if (sig.optionalParametersAreNamed) { | 579 if (sig.optionalParametersAreNamed) { |
576 for (FormalElement param in sig.orderedOptionalParameters) { | 580 for (FormalElement param in sig.orderedOptionalParameters) { |
577 suffixes.add(param.name); | 581 suffixes.add(param.name); |
578 } | 582 } |
579 } | 583 } |
580 return suffixes; | 584 return suffixes; |
581 } | 585 } |
582 | 586 |
583 /// Annotated name for the member being invoked by [selector]. | 587 /// Annotated name for the member being invoked by [selector]. |
584 String invocationName(Selector selector) { | 588 String invocationName(Selector selector) { |
585 LibraryElement library = selector.library; | |
586 switch (selector.kind) { | 589 switch (selector.kind) { |
587 case SelectorKind.GETTER: | 590 case SelectorKind.GETTER: |
588 String disambiguatedName = _disambiguateMember(library, selector.name); | 591 String disambiguatedName = _disambiguateMember(selector.memberName); |
589 return deriveGetterName(disambiguatedName); | 592 return deriveGetterName(disambiguatedName); |
590 | 593 |
591 case SelectorKind.SETTER: | 594 case SelectorKind.SETTER: |
592 String disambiguatedName = _disambiguateMember(library, selector.name); | 595 String disambiguatedName = _disambiguateMember(selector.memberName); |
593 return deriveSetterName(disambiguatedName); | 596 return deriveSetterName(disambiguatedName); |
594 | 597 |
595 case SelectorKind.OPERATOR: | 598 case SelectorKind.OPERATOR: |
596 case SelectorKind.INDEX: | 599 case SelectorKind.INDEX: |
597 String operatorIdentifier = operatorNameToIdentifier(selector.name); | 600 String operatorIdentifier = operatorNameToIdentifier(selector.name); |
598 String disambiguatedName = _disambiguateOperator(operatorIdentifier); | 601 String disambiguatedName = _disambiguateOperator(operatorIdentifier); |
599 return disambiguatedName; // Operators are not annotated. | 602 return disambiguatedName; // Operators are not annotated. |
600 | 603 |
601 case SelectorKind.CALL: | 604 case SelectorKind.CALL: |
602 List<String> suffix = callSuffixForSelector(selector); | 605 List<String> suffix = callSuffixForStructure(selector.callStructure); |
603 if (selector.name == Compiler.CALL_OPERATOR_NAME) { | 606 if (selector.name == Compiler.CALL_OPERATOR_NAME) { |
604 // Derive the annotated name for this variant of 'call'. | 607 // Derive the annotated name for this variant of 'call'. |
605 return deriveCallMethodName(suffix); | 608 return deriveCallMethodName(suffix); |
606 } | 609 } |
607 String disambiguatedName = | 610 String disambiguatedName = |
608 _disambiguateMember(library, selector.name, suffix); | 611 _disambiguateMember(selector.memberName, suffix); |
609 return disambiguatedName; // Methods other than call are not annotated. | 612 return disambiguatedName; // Methods other than call are not annotated. |
610 | 613 |
611 default: | 614 default: |
612 compiler.internalError(compiler.currentElement, | 615 compiler.internalError(compiler.currentElement, |
613 'Unexpected selector kind: ${selector.kind}'); | 616 'Unexpected selector kind: ${selector.kind}'); |
614 return null; | 617 return null; |
615 } | 618 } |
616 } | 619 } |
617 | 620 |
618 /** | 621 /** |
619 * Returns the internal name used for an invocation mirror of this selector. | 622 * Returns the internal name used for an invocation mirror of this selector. |
620 */ | 623 */ |
621 String invocationMirrorInternalName(Selector selector) | 624 String invocationMirrorInternalName(Selector selector) |
622 => invocationName(selector); | 625 => invocationName(selector); |
623 | 626 |
624 /** | 627 /** |
625 * Returns the disambiguated name for the given field, used for constructing | 628 * Returns the disambiguated name for the given field, used for constructing |
626 * the getter and setter names. | 629 * the getter and setter names. |
627 */ | 630 */ |
628 String fieldAccessorName(Element element) { | 631 String fieldAccessorName(FieldElement element) { |
629 return element.isInstanceMember | 632 return element.isInstanceMember |
630 ? _disambiguateMember(element.library, element.name) | 633 ? _disambiguateMember(element.memberName) |
631 : _disambiguateGlobal(element); | 634 : _disambiguateGlobal(element); |
632 } | 635 } |
633 | 636 |
634 /** | 637 /** |
635 * Returns name of the JavaScript property used to store a static or instance | 638 * Returns name of the JavaScript property used to store a static or instance |
636 * field. | 639 * field. |
637 */ | 640 */ |
638 String fieldPropertyName(Element element) { | 641 String fieldPropertyName(FieldElement element) { |
639 return element.isInstanceMember | 642 return element.isInstanceMember |
640 ? instanceFieldPropertyName(element) | 643 ? instanceFieldPropertyName(element) |
641 : _disambiguateGlobal(element); | 644 : _disambiguateGlobal(element); |
642 } | 645 } |
643 | 646 |
644 /** | 647 /** |
645 * Returns name of the JavaScript property used to store the | 648 * Returns name of the JavaScript property used to store the |
646 * `readTypeVariable` function for the given type variable. | 649 * `readTypeVariable` function for the given type variable. |
647 */ | 650 */ |
648 String nameForReadTypeVariable(TypeVariableElement element) { | 651 String nameForReadTypeVariable(TypeVariableElement element) { |
649 return _disambiguateInternalMember(element, () => element.name); | 652 return _disambiguateInternalMember(element, () => element.name); |
650 } | 653 } |
651 | 654 |
652 /** | 655 /** |
653 * Returns a JavaScript property name used to store [element] on one | 656 * Returns a JavaScript property name used to store [element] on one |
654 * of the global objects. | 657 * of the global objects. |
655 * | 658 * |
656 * Should be used together with [globalObjectFor], which denotes the object | 659 * Should be used together with [globalObjectFor], which denotes the object |
657 * on which the returned property name should be used. | 660 * on which the returned property name should be used. |
658 */ | 661 */ |
659 String globalPropertyName(Element element) { | 662 String globalPropertyName(Element element) { |
660 return _disambiguateGlobal(element); | 663 return _disambiguateGlobal(element); |
661 } | 664 } |
662 | 665 |
663 /** | 666 /** |
664 * Returns the JavaScript property name used to store an instance field. | 667 * Returns the JavaScript property name used to store an instance field. |
665 */ | 668 */ |
666 String instanceFieldPropertyName(Element element) { | 669 String instanceFieldPropertyName(FieldElement element) { |
667 ClassElement enclosingClass = element.enclosingClass; | 670 ClassElement enclosingClass = element.enclosingClass; |
668 | 671 |
669 if (element.hasFixedBackendName) { | 672 if (element.hasFixedBackendName) { |
670 // Certain native fields must be given a specific name. Native names must | 673 // Certain native fields must be given a specific name. Native names must |
671 // not contain '$'. We rely on this to avoid clashes. | 674 // not contain '$'. We rely on this to avoid clashes. |
672 assert(enclosingClass.isNative && | 675 assert(enclosingClass.isNative && |
673 !element.fixedBackendName.contains(r'$')); | 676 !element.fixedBackendName.contains(r'$')); |
674 | 677 |
675 return element.fixedBackendName; | 678 return element.fixedBackendName; |
676 } | 679 } |
(...skipping 19 matching lines...) Expand all Loading... |
696 if (classWorld.isUsedAsMixin(enclosingClass) || | 699 if (classWorld.isUsedAsMixin(enclosingClass) || |
697 _isShadowingSuperField(element) || | 700 _isShadowingSuperField(element) || |
698 _isUserClassExtendingNative(enclosingClass)) { | 701 _isUserClassExtendingNative(enclosingClass)) { |
699 String proposeName() => '${enclosingClass.name}_${element.name}'; | 702 String proposeName() => '${enclosingClass.name}_${element.name}'; |
700 return _disambiguateInternalMember(element, proposeName); | 703 return _disambiguateInternalMember(element, proposeName); |
701 } | 704 } |
702 | 705 |
703 // No superclass uses the disambiguated name as a property name, so we can | 706 // No superclass uses the disambiguated name as a property name, so we can |
704 // use it for this field. This generates nicer field names since otherwise | 707 // use it for this field. This generates nicer field names since otherwise |
705 // the field name would have to be mangled. | 708 // the field name would have to be mangled. |
706 return _disambiguateMember(element.library, element.name); | 709 return _disambiguateMember(element.memberName); |
707 } | 710 } |
708 | 711 |
709 bool _isShadowingSuperField(Element element) { | 712 bool _isShadowingSuperField(Element element) { |
710 return element.enclosingClass.hasFieldShadowedBy(element); | 713 return element.enclosingClass.hasFieldShadowedBy(element); |
711 } | 714 } |
712 | 715 |
713 /// True if [class_] is a non-native class that inherits from a native class. | 716 /// True if [class_] is a non-native class that inherits from a native class. |
714 bool _isUserClassExtendingNative(ClassElement class_) { | 717 bool _isUserClassExtendingNative(ClassElement class_) { |
715 return !class_.isNative && | 718 return !class_.isNative && |
716 Elements.isNativeOrExtendsNative(class_.superclass); | 719 Elements.isNativeOrExtendsNative(class_.superclass); |
717 } | 720 } |
718 | 721 |
719 /// Annotated name for the setter of [element]. | 722 /// Annotated name for the setter of [element]. |
720 String setterForElement(Element element) { | 723 String setterForElement(MemberElement element) { |
721 // We dynamically create setters from the field-name. The setter name must | 724 // We dynamically create setters from the field-name. The setter name must |
722 // therefore be derived from the instance field-name. | 725 // therefore be derived from the instance field-name. |
723 String name = _disambiguateMember(element.library, element.name); | 726 String name = _disambiguateMember(element.memberName); |
724 return deriveSetterName(name); | 727 return deriveSetterName(name); |
725 } | 728 } |
726 | 729 |
727 /// Annotated name for the setter of any member with [disambiguatedName]. | 730 /// Annotated name for the setter of any member with [disambiguatedName]. |
728 String deriveSetterName(String disambiguatedName) { | 731 String deriveSetterName(String disambiguatedName) { |
729 // We dynamically create setters from the field-name. The setter name must | 732 // We dynamically create setters from the field-name. The setter name must |
730 // therefore be derived from the instance field-name. | 733 // therefore be derived from the instance field-name. |
731 return '$setterPrefix$disambiguatedName'; | 734 return '$setterPrefix$disambiguatedName'; |
732 } | 735 } |
733 | 736 |
734 /// Annotated name for the setter of any member with [disambiguatedName]. | 737 /// Annotated name for the setter of any member with [disambiguatedName]. |
735 String deriveGetterName(String disambiguatedName) { | 738 String deriveGetterName(String disambiguatedName) { |
736 // We dynamically create getters from the field-name. The getter name must | 739 // We dynamically create getters from the field-name. The getter name must |
737 // therefore be derived from the instance field-name. | 740 // therefore be derived from the instance field-name. |
738 return '$getterPrefix$disambiguatedName'; | 741 return '$getterPrefix$disambiguatedName'; |
739 } | 742 } |
740 | 743 |
741 /// Annotated name for the getter of [element]. | 744 /// Annotated name for the getter of [element]. |
742 String getterForElement(Element element) { | 745 String getterForElement(MemberElement element) { |
743 // We dynamically create getters from the field-name. The getter name must | 746 // We dynamically create getters from the field-name. The getter name must |
744 // therefore be derived from the instance field-name. | 747 // therefore be derived from the instance field-name. |
745 String name = _disambiguateMember(element.library, element.name); | 748 String name = _disambiguateMember(element.memberName); |
746 return deriveGetterName(name); | 749 return deriveGetterName(name); |
747 } | 750 } |
748 | 751 |
749 /// Property name for the getter of an instance member with [originalName] | 752 /// Property name for the getter of an instance member with [originalName]. |
750 /// in [library]. | 753 String getterForMember(Name originalName) { |
751 /// | 754 String disambiguatedName = _disambiguateMember(originalName); |
752 /// [library] may be `null` if [originalName] is known to be public. | |
753 String getterForMember(LibraryElement library, String originalName) { | |
754 String disambiguatedName = _disambiguateMember(library, originalName); | |
755 return deriveGetterName(disambiguatedName); | 755 return deriveGetterName(disambiguatedName); |
756 } | 756 } |
757 | 757 |
758 /// Property name for the getter or a public instance member with | |
759 /// [originalName]. | |
760 String getterForPublicMember(String originalName) { | |
761 return getterForMember(null, originalName); | |
762 } | |
763 | |
764 /// Disambiguated name for a compiler-owned global variable. | 758 /// Disambiguated name for a compiler-owned global variable. |
765 /// | 759 /// |
766 /// The resulting name is unique within the global-member namespace. | 760 /// The resulting name is unique within the global-member namespace. |
767 String _disambiguateInternalGlobal(String name) { | 761 String _disambiguateInternalGlobal(String name) { |
768 String newName = internalGlobals[name]; | 762 String newName = internalGlobals[name]; |
769 if (newName == null) { | 763 if (newName == null) { |
770 newName = getFreshName(name, usedGlobalNames, suggestedGlobalNames); | 764 newName = getFreshName(name, usedGlobalNames, suggestedGlobalNames); |
771 internalGlobals[name] = newName; | 765 internalGlobals[name] = newName; |
772 } | 766 } |
773 return newName; | 767 return newName; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 /// and setters) and as property name for storing methods and method stubs. | 809 /// and setters) and as property name for storing methods and method stubs. |
816 /// | 810 /// |
817 /// [suffixes] denote an extension of [originalName] to distiguish it from | 811 /// [suffixes] denote an extension of [originalName] to distiguish it from |
818 /// other members with that name. These are used to encode the arity and | 812 /// other members with that name. These are used to encode the arity and |
819 /// named parameters to a method. Disambiguating the same [originalName] with | 813 /// named parameters to a method. Disambiguating the same [originalName] with |
820 /// different [suffixes] will yield different disambiguated names. | 814 /// different [suffixes] will yield different disambiguated names. |
821 /// | 815 /// |
822 /// The resulting name, and its associated annotated names, are unique | 816 /// The resulting name, and its associated annotated names, are unique |
823 /// to the ([originalName], [suffixes]) pair within the instance-member | 817 /// to the ([originalName], [suffixes]) pair within the instance-member |
824 /// namespace. | 818 /// namespace. |
825 String _disambiguateMember(LibraryElement library, | 819 String _disambiguateMember(Name originalName, |
826 String originalName, | |
827 [List<String> suffixes = const []]) { | 820 [List<String> suffixes = const []]) { |
828 // For private names, a library must be given. | |
829 assert(isPublicName(originalName) || library != null); | |
830 | |
831 // Build a string encoding the library name, if the name is private. | 821 // Build a string encoding the library name, if the name is private. |
832 String libraryKey = isPrivateName(originalName) | 822 String libraryKey = originalName.isPrivate |
833 ? _disambiguateGlobal(library) | 823 ? _disambiguateGlobal(originalName.library) |
834 : ''; | 824 : ''; |
835 | 825 |
836 // In the unique key, separate the name parts by '@'. | 826 // In the unique key, separate the name parts by '@'. |
837 // This avoids clashes since the original names cannot contain that symbol. | 827 // This avoids clashes since the original names cannot contain that symbol. |
838 String key = '$libraryKey@$originalName@${suffixes.join('@')}'; | 828 String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}'; |
839 String newName = userInstanceMembers[key]; | 829 String newName = userInstanceMembers[key]; |
840 if (newName == null) { | 830 if (newName == null) { |
841 String proposedName = privateName(library, originalName); | 831 String proposedName = privateName(originalName); |
842 if (!suffixes.isEmpty) { | 832 if (!suffixes.isEmpty) { |
843 // In the proposed name, separate the name parts by '$', because the | 833 // In the proposed name, separate the name parts by '$', because the |
844 // proposed name must be a valid identifier, but not necessarily unique. | 834 // proposed name must be a valid identifier, but not necessarily unique. |
845 proposedName += r'$' + suffixes.join(r'$'); | 835 proposedName += r'$' + suffixes.join(r'$'); |
846 } | 836 } |
847 newName = getFreshName(proposedName, | 837 newName = getFreshName(proposedName, |
848 usedInstanceNames, suggestedInstanceNames, | 838 usedInstanceNames, suggestedInstanceNames, |
849 sanitizeForAnnotations: true); | 839 sanitizeForAnnotations: true); |
850 userInstanceMembers[key] = newName; | 840 userInstanceMembers[key] = newName; |
851 } | 841 } |
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 if (!first) { | 1758 if (!first) { |
1769 sb.write('_'); | 1759 sb.write('_'); |
1770 } | 1760 } |
1771 sb.write('_'); | 1761 sb.write('_'); |
1772 visit(parameter); | 1762 visit(parameter); |
1773 first = true; | 1763 first = true; |
1774 } | 1764 } |
1775 } | 1765 } |
1776 } | 1766 } |
1777 } | 1767 } |
OLD | NEW |