| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 * (The [getterPrefix] and [setterPrefix] are different in [MinifyNamer]). | 94 * (The [getterPrefix] and [setterPrefix] are different in [MinifyNamer]). |
| 95 * | 95 * |
| 96 * 3. The `is` and operator uses the following names: | 96 * 3. The `is` and operator uses the following names: |
| 97 * | 97 * |
| 98 * $is<NAME> | 98 * $is<NAME> |
| 99 * $as<NAME> | 99 * $as<NAME> |
| 100 * | 100 * |
| 101 * For local variables, the [Namer] only provides *proposed names*. These names | 101 * For local variables, the [Namer] only provides *proposed names*. These names |
| 102 * must be disambiguated elsewhere. | 102 * must be disambiguated elsewhere. |
| 103 */ | 103 */ |
| 104 class Namer implements ClosureNamer { | 104 class Namer { |
| 105 | 105 |
| 106 static const List<String> javaScriptKeywords = const <String>[ | 106 static const List<String> javaScriptKeywords = const <String>[ |
| 107 // These are current keywords. | 107 // These are current keywords. |
| 108 "break", "delete", "function", "return", "typeof", "case", "do", "if", | 108 "break", "delete", "function", "return", "typeof", "case", "do", "if", |
| 109 "switch", "var", "catch", "else", "in", "this", "void", "continue", | 109 "switch", "var", "catch", "else", "in", "this", "void", "continue", |
| 110 "false", "instanceof", "throw", "while", "debugger", "finally", "new", | 110 "false", "instanceof", "throw", "while", "debugger", "finally", "new", |
| 111 "true", "with", "default", "for", "null", "try", | 111 "true", "with", "default", "for", "null", "try", |
| 112 | 112 |
| 113 // These are future keywords. | 113 // These are future keywords. |
| 114 "abstract", "double", "goto", "native", "static", "boolean", "enum", | 114 "abstract", "double", "goto", "native", "static", "boolean", "enum", |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 return _disambiguateGlobal(element); | 656 return _disambiguateGlobal(element); |
| 657 } | 657 } |
| 658 | 658 |
| 659 /** | 659 /** |
| 660 * Returns the JavaScript property name used to store an instance field. | 660 * Returns the JavaScript property name used to store an instance field. |
| 661 */ | 661 */ |
| 662 String instanceFieldPropertyName(Element element) { | 662 String instanceFieldPropertyName(Element element) { |
| 663 ClassElement enclosingClass = element.enclosingClass; | 663 ClassElement enclosingClass = element.enclosingClass; |
| 664 | 664 |
| 665 if (element.hasFixedBackendName) { | 665 if (element.hasFixedBackendName) { |
| 666 // Box fields and certain native fields must be given a specific name. | 666 // Certain native fields must be given a specific name. Native names must |
| 667 // Native names must not contain '$'. We rely on this to avoid clashes. | 667 // not contain '$'. We rely on this to avoid clashes. |
| 668 assert(element is BoxFieldElement || | 668 assert(enclosingClass.isNative && |
| 669 enclosingClass.isNative && !element.fixedBackendName.contains(r'$')); | 669 !element.fixedBackendName.contains(r'$')); |
| 670 | 670 |
| 671 return element.fixedBackendName; | 671 return element.fixedBackendName; |
| 672 } | 672 } |
| 673 | 673 |
| 674 // Instances of BoxFieldElement are special. They are already created with |
| 675 // a unique and safe name. However, as boxes are not really instances of |
| 676 // classes, the usual naming scheme that tries to avoid name clashes with |
| 677 // super classes does not apply. We still do not mark the name as a |
| 678 // fixedBackendName, as we want to allow other namers to do something more |
| 679 // clever with them. |
| 680 if (element is BoxFieldElement) { |
| 681 return element.name; |
| 682 } |
| 683 |
| 674 // If the name of the field might clash with another field, | 684 // If the name of the field might clash with another field, |
| 675 // use a mangled field name to avoid potential clashes. | 685 // use a mangled field name to avoid potential clashes. |
| 676 // Note that if the class extends a native class, that native class might | 686 // Note that if the class extends a native class, that native class might |
| 677 // have fields with fixed backend names, so we assume the worst and always | 687 // have fields with fixed backend names, so we assume the worst and always |
| 678 // mangle the field names of classes extending native classes. | 688 // mangle the field names of classes extending native classes. |
| 679 // Methods on such classes are stored on the interceptor, not the instance, | 689 // Methods on such classes are stored on the interceptor, not the instance, |
| 680 // so only fields have the potential to clash with a native property name. | 690 // so only fields have the potential to clash with a native property name. |
| 681 ClassWorld classWorld = compiler.world; | 691 ClassWorld classWorld = compiler.world; |
| 682 if (classWorld.isUsedAsMixin(enclosingClass) || | 692 if (classWorld.isUsedAsMixin(enclosingClass) || |
| 683 _isShadowingSuperField(element) || | 693 _isShadowingSuperField(element) || |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 /// If [name] is not an annotated name, the result will not be an annotated | 975 /// If [name] is not an annotated name, the result will not be an annotated |
| 966 /// name either. | 976 /// name either. |
| 967 String _sanitizeForNatives(String name) { | 977 String _sanitizeForNatives(String name) { |
| 968 if (!name.contains(r'$')) { | 978 if (!name.contains(r'$')) { |
| 969 // Prepend $$. The result must not coincide with an annotated name. | 979 // Prepend $$. The result must not coincide with an annotated name. |
| 970 name = '\$\$$name'; | 980 name = '\$\$$name'; |
| 971 } | 981 } |
| 972 return name; | 982 return name; |
| 973 } | 983 } |
| 974 | 984 |
| 975 /// Generate a unique name for the [id]th closure variable, with proposed name | |
| 976 /// [name]. | |
| 977 /// | |
| 978 /// The result is used as the name of [BoxFieldElement]s and | |
| 979 /// [ClosureFieldElement]s, and must therefore be unique to avoid breaking an | |
| 980 /// invariant in the element model (classes cannot declare multiple fields | |
| 981 /// with the same name). | |
| 982 /// | |
| 983 /// Since the result is used as an element name, it will later show up as a | |
| 984 /// *proposed name* when the element is passed to [instanceFieldPropertyName]. | |
| 985 String getClosureVariableName(String name, int id) { | |
| 986 return "${name}_$id"; | |
| 987 } | |
| 988 | |
| 989 /** | 985 /** |
| 990 * Returns a proposed name for the given top-level or static element. | 986 * Returns a proposed name for the given top-level or static element. |
| 991 * The returned id is guaranteed to be a valid JS-id. | 987 * The returned id is guaranteed to be a valid JS-id. |
| 992 */ | 988 */ |
| 993 String _proposeNameForGlobal(Element element) { | 989 String _proposeNameForGlobal(Element element) { |
| 994 assert(!element.isInstanceMember); | 990 assert(!element.isInstanceMember); |
| 995 String name; | 991 String name; |
| 996 if (element.isGenerativeConstructor) { | 992 if (element.isGenerativeConstructor) { |
| 997 name = "${element.enclosingClass.name}\$" | 993 name = "${element.enclosingClass.name}\$" |
| 998 "${element.name}"; | 994 "${element.name}"; |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 if (!first) { | 1765 if (!first) { |
| 1770 sb.write('_'); | 1766 sb.write('_'); |
| 1771 } | 1767 } |
| 1772 sb.write('_'); | 1768 sb.write('_'); |
| 1773 visit(parameter); | 1769 visit(parameter); |
| 1774 first = true; | 1770 first = true; |
| 1775 } | 1771 } |
| 1776 } | 1772 } |
| 1777 } | 1773 } |
| 1778 } | 1774 } |
| OLD | NEW |