Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/namer.dart

Issue 68203020: Reapply "Fix issues with field names by ensuring that fields have exactly one name regardless of ho… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698