| 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 library js_backend.namer; | 5 library js_backend.namer; |
| 6 | 6 |
| 7 import 'dart:collection' show HashMap; | 7 import 'dart:collection' show HashMap; |
| 8 | 8 |
| 9 import 'package:js_runtime/shared/embedded_names.dart' show JsGetName; | 9 import 'package:js_runtime/shared/embedded_names.dart' show JsGetName; |
| 10 | 10 |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 return '$name\$${suffix.join(r'$')}'; | 765 return '$name\$${suffix.join(r'$')}'; |
| 766 } | 766 } |
| 767 | 767 |
| 768 /// Name for a constructor body. | 768 /// Name for a constructor body. |
| 769 jsAst.Name constructorBodyName(FunctionElement ctor) { | 769 jsAst.Name constructorBodyName(FunctionElement ctor) { |
| 770 return _disambiguateInternalMember( | 770 return _disambiguateInternalMember( |
| 771 ctor, () => _proposeNameForConstructorBody(ctor)); | 771 ctor, () => _proposeNameForConstructorBody(ctor)); |
| 772 } | 772 } |
| 773 | 773 |
| 774 /// Annotated name for [method] encoding arity and named parameters. | 774 /// Annotated name for [method] encoding arity and named parameters. |
| 775 jsAst.Name instanceMethodName(MethodElement method) { | 775 jsAst.Name instanceMethodName(FunctionEntity method) { |
| 776 if (method.isGenerativeConstructorBody) { | 776 // TODO(johnniwinther): Avoid the use of [ConstructorBodyElement]. The |
| 777 // codegen model should be explicit about its constructor body elements. |
| 778 if (method is ConstructorBodyElement) { |
| 777 return constructorBodyName(method); | 779 return constructorBodyName(method); |
| 778 } | 780 } |
| 779 return invocationName(new Selector.fromElement(method)); | 781 return invocationName(new Selector.fromElement(method)); |
| 780 } | 782 } |
| 781 | 783 |
| 782 /// Returns the annotated name for a variant of `call`. | 784 /// Returns the annotated name for a variant of `call`. |
| 783 /// The result has the form: | 785 /// The result has the form: |
| 784 /// | 786 /// |
| 785 /// call$<N>$namedParam1...$namedParam<M> | 787 /// call$<N>$namedParam1...$namedParam<M> |
| 786 /// | 788 /// |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 return element.name.replaceAll('+', '_'); | 1288 return element.name.replaceAll('+', '_'); |
| 1287 } | 1289 } |
| 1288 | 1290 |
| 1289 String _proposeNameForConstructor(ConstructorEntity element) { | 1291 String _proposeNameForConstructor(ConstructorEntity element) { |
| 1290 String className = element.enclosingClass.name; | 1292 String className = element.enclosingClass.name; |
| 1291 if (element.isGenerativeConstructor) { | 1293 if (element.isGenerativeConstructor) { |
| 1292 return '${className}\$${element.name}'; | 1294 return '${className}\$${element.name}'; |
| 1293 } else { | 1295 } else { |
| 1294 // TODO(johnniwinther): Change factory name encoding as to not include | 1296 // TODO(johnniwinther): Change factory name encoding as to not include |
| 1295 // the class-name twice. | 1297 // the class-name twice. |
| 1296 String constructorName; | 1298 return '${className}_${Elements.reconstructConstructorName(element)}'; |
| 1297 if (element.name == '') { | |
| 1298 constructorName = className; | |
| 1299 } else { | |
| 1300 constructorName = '${className}\$${element.name}'; | |
| 1301 } | |
| 1302 return '${className}_${constructorName}'; | |
| 1303 } | 1299 } |
| 1304 } | 1300 } |
| 1305 | 1301 |
| 1306 /** | 1302 /** |
| 1307 * Returns a proposed name for the given [LibraryElement]. | 1303 * Returns a proposed name for the given [LibraryElement]. |
| 1308 * The returned id is guaranteed to be a valid JavaScript identifier. | 1304 * The returned id is guaranteed to be a valid JavaScript identifier. |
| 1309 */ | 1305 */ |
| 1310 // TODO(sra): Pre-process libraries to assign [libraryLongNames] in a way that | 1306 // TODO(sra): Pre-process libraries to assign [libraryLongNames] in a way that |
| 1311 // is independent of the order of calls to namer. | 1307 // is independent of the order of calls to namer. |
| 1312 String _proposeNameForLibrary(LibraryEntity library) { | 1308 String _proposeNameForLibrary(LibraryEntity library) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 | 1410 |
| 1415 /// Returns the runtime name for [element]. | 1411 /// Returns the runtime name for [element]. |
| 1416 /// | 1412 /// |
| 1417 /// This name is used as the basis for deriving `is` and `as` property names | 1413 /// This name is used as the basis for deriving `is` and `as` property names |
| 1418 /// for the given type. | 1414 /// for the given type. |
| 1419 /// | 1415 /// |
| 1420 /// The result is not always safe as a property name unless prefixing | 1416 /// The result is not always safe as a property name unless prefixing |
| 1421 /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type, | 1417 /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type, |
| 1422 /// then by convention, an underscore must also separate [operatorIsPrefix] | 1418 /// then by convention, an underscore must also separate [operatorIsPrefix] |
| 1423 /// from the type name. | 1419 /// from the type name. |
| 1424 jsAst.Name runtimeTypeName(TypeDeclarationElement element) { | 1420 jsAst.Name runtimeTypeName(Entity element) { |
| 1425 if (element == null) return _literalDynamic; | 1421 if (element == null) return _literalDynamic; |
| 1426 // The returned name affects both the global and instance member namespaces: | 1422 // The returned name affects both the global and instance member namespaces: |
| 1427 // | 1423 // |
| 1428 // - If given a class, this must coincide with the class name, which | 1424 // - If given a class, this must coincide with the class name, which |
| 1429 // is also the GLOBAL property name of its constructor. | 1425 // is also the GLOBAL property name of its constructor. |
| 1430 // | 1426 // |
| 1431 // - The result is used to derive `$isX` and `$asX` names, which are used | 1427 // - The result is used to derive `$isX` and `$asX` names, which are used |
| 1432 // as INSTANCE property names. | 1428 // as INSTANCE property names. |
| 1433 // | 1429 // |
| 1434 // To prevent clashes in both namespaces at once, we disambiguate the name | 1430 // To prevent clashes in both namespaces at once, we disambiguate the name |
| 1435 // as a global here, and in [_sanitizeForAnnotations] we ensure that | 1431 // as a global here, and in [_sanitizeForAnnotations] we ensure that |
| 1436 // ordinary instance members cannot start with `$is` or `$as`. | 1432 // ordinary instance members cannot start with `$is` or `$as`. |
| 1437 return _disambiguateGlobalType(element); | 1433 return _disambiguateGlobalType(element); |
| 1438 } | 1434 } |
| 1439 | 1435 |
| 1440 /// Returns the disambiguated name of [class_]. | 1436 /// Returns the disambiguated name of [class_]. |
| 1441 /// | 1437 /// |
| 1442 /// This is both the *runtime type* of the class (see [runtimeTypeName]) | 1438 /// This is both the *runtime type* of the class (see [runtimeTypeName]) |
| 1443 /// and a global property name in which to store its JS constructor. | 1439 /// and a global property name in which to store its JS constructor. |
| 1444 jsAst.Name className(ClassElement class_) => _disambiguateGlobalType(class_); | 1440 jsAst.Name className(ClassEntity class_) => _disambiguateGlobalType(class_); |
| 1445 | 1441 |
| 1446 /// Property name on which [member] can be accessed directly, | 1442 /// Property name on which [member] can be accessed directly, |
| 1447 /// without clashing with another JS property name. | 1443 /// without clashing with another JS property name. |
| 1448 /// | 1444 /// |
| 1449 /// This is used for implementing super-calls, where ordinary dispatch | 1445 /// This is used for implementing super-calls, where ordinary dispatch |
| 1450 /// semantics must be circumvented. For example: | 1446 /// semantics must be circumvented. For example: |
| 1451 /// | 1447 /// |
| 1452 /// class A { foo() } | 1448 /// class A { foo() } |
| 1453 /// class B extends A { | 1449 /// class B extends A { |
| 1454 /// foo() { super.foo() } | 1450 /// foo() { super.foo() } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1470 return "super\$${member.enclosingClass.name}\$$invocationName"; | 1466 return "super\$${member.enclosingClass.name}\$$invocationName"; |
| 1471 }); | 1467 }); |
| 1472 } | 1468 } |
| 1473 | 1469 |
| 1474 /// Property name in which to store the given static or instance [method]. | 1470 /// Property name in which to store the given static or instance [method]. |
| 1475 /// For instance methods, this includes the suffix encoding arity and named | 1471 /// For instance methods, this includes the suffix encoding arity and named |
| 1476 /// parameters. | 1472 /// parameters. |
| 1477 /// | 1473 /// |
| 1478 /// The name is not necessarily unique to [method], since a static method | 1474 /// The name is not necessarily unique to [method], since a static method |
| 1479 /// may share its name with an instance method. | 1475 /// may share its name with an instance method. |
| 1480 jsAst.Name methodPropertyName(MethodElement method) { | 1476 jsAst.Name methodPropertyName(FunctionEntity method) { |
| 1481 return method.isInstanceMember | 1477 return method.isInstanceMember |
| 1482 ? instanceMethodName(method) | 1478 ? instanceMethodName(method) |
| 1483 : globalPropertyNameForMember(method); | 1479 : globalPropertyNameForMember(method); |
| 1484 } | 1480 } |
| 1485 | 1481 |
| 1486 /// Returns true if [element] is stored in the static state holder | 1482 /// Returns true if [element] is stored in the static state holder |
| 1487 /// ([staticStateHolder]). We intend to store only mutable static state | 1483 /// ([staticStateHolder]). We intend to store only mutable static state |
| 1488 /// there, whereas constants are stored in 'C'. Functions, accessors, | 1484 /// there, whereas constants are stored in 'C'. Functions, accessors, |
| 1489 /// classes, etc. are stored in one of the other objects in | 1485 /// classes, etc. are stored in one of the other objects in |
| 1490 /// [reservedGlobalObjectNames]. | 1486 /// [reservedGlobalObjectNames]. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1503 !element.isClass && | 1499 !element.isClass && |
| 1504 !element.isTypedef && | 1500 !element.isTypedef && |
| 1505 !element.isConstructor && | 1501 !element.isConstructor && |
| 1506 !element.isFunction && | 1502 !element.isFunction && |
| 1507 !element.isLibrary; | 1503 !element.isLibrary; |
| 1508 } | 1504 } |
| 1509 return element.isField; | 1505 return element.isField; |
| 1510 } | 1506 } |
| 1511 | 1507 |
| 1512 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames]. | 1508 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames]. |
| 1513 // TODO(johnniwinther): Verify that the implementation can be changed to | |
| 1514 // `globalObjectForLibrary(element.library)`. | |
| 1515 String globalObjectForMethod(MethodElement element) => | |
| 1516 globalObjectForMember(element); | |
| 1517 | |
| 1518 /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames]. | |
| 1519 String globalObjectForMember(MemberEntity element) { | 1509 String globalObjectForMember(MemberEntity element) { |
| 1520 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder; | 1510 if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder; |
| 1521 return globalObjectForLibrary(element.library); | 1511 return globalObjectForLibrary(element.library); |
| 1522 } | 1512 } |
| 1523 | 1513 |
| 1524 String globalObjectForClass(ClassEntity element) { | 1514 String globalObjectForClass(ClassEntity element) { |
| 1525 return globalObjectForLibrary(element.library); | 1515 return globalObjectForLibrary(element.library); |
| 1526 } | 1516 } |
| 1527 | 1517 |
| 1528 String globalObjectForType(Entity element) { | 1518 String globalObjectForType(Entity element) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1549 return new CompoundName([_literalLazyGetterPrefix, name]); | 1539 return new CompoundName([_literalLazyGetterPrefix, name]); |
| 1550 } | 1540 } |
| 1551 | 1541 |
| 1552 jsAst.Name lazyInitializerName(FieldEntity element) { | 1542 jsAst.Name lazyInitializerName(FieldEntity element) { |
| 1553 assert(element.isTopLevel || element.isStatic); | 1543 assert(element.isTopLevel || element.isStatic); |
| 1554 jsAst.Name name = _disambiguateGlobalMember(element); | 1544 jsAst.Name name = _disambiguateGlobalMember(element); |
| 1555 // These are not real dart getters, so do not use GetterName; | 1545 // These are not real dart getters, so do not use GetterName; |
| 1556 return deriveLazyInitializerName(name); | 1546 return deriveLazyInitializerName(name); |
| 1557 } | 1547 } |
| 1558 | 1548 |
| 1559 jsAst.Name staticClosureName(Element element) { | 1549 jsAst.Name staticClosureName(FunctionEntity element) { |
| 1560 assert(Elements.isStaticOrTopLevelFunction(element)); | 1550 assert(element.isTopLevel || element.isStatic); |
| 1561 String enclosing = | 1551 String enclosing = |
| 1562 element.enclosingClass == null ? "" : element.enclosingClass.name; | 1552 element.enclosingClass == null ? "" : element.enclosingClass.name; |
| 1563 String library = _proposeNameForLibrary(element.library); | 1553 String library = _proposeNameForLibrary(element.library); |
| 1564 return _disambiguateInternalGlobal( | 1554 return _disambiguateInternalGlobal( |
| 1565 "${library}_${enclosing}_${element.name}\$closure"); | 1555 "${library}_${enclosing}_${element.name}\$closure"); |
| 1566 } | 1556 } |
| 1567 | 1557 |
| 1568 // This name is used as part of the name of a TypeConstant | 1558 // This name is used as part of the name of a TypeConstant |
| 1569 String uniqueNameForTypeConstantElement( | 1559 String uniqueNameForTypeConstantElement( |
| 1570 LibraryEntity library, Entity element) { | 1560 LibraryEntity library, Entity element) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 return new CompoundName([ | 1605 return new CompoundName([ |
| 1616 new StringBackedName(operatorIsPrefix), | 1606 new StringBackedName(operatorIsPrefix), |
| 1617 _literalUnderscore, | 1607 _literalUnderscore, |
| 1618 getFunctionTypeName(type) | 1608 getFunctionTypeName(type) |
| 1619 ]); | 1609 ]); |
| 1620 } | 1610 } |
| 1621 InterfaceType interfaceType = type; | 1611 InterfaceType interfaceType = type; |
| 1622 return operatorIs(interfaceType.element); | 1612 return operatorIs(interfaceType.element); |
| 1623 } | 1613 } |
| 1624 | 1614 |
| 1625 jsAst.Name operatorIs(ClassElement element) { | 1615 jsAst.Name operatorIs(ClassEntity element) { |
| 1626 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | 1616 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. |
| 1627 return new CompoundName( | 1617 return new CompoundName( |
| 1628 [new StringBackedName(operatorIsPrefix), runtimeTypeName(element)]); | 1618 [new StringBackedName(operatorIsPrefix), runtimeTypeName(element)]); |
| 1629 } | 1619 } |
| 1630 | 1620 |
| 1631 /// Returns a name that does not clash with reserved JS keywords. | 1621 /// Returns a name that does not clash with reserved JS keywords. |
| 1632 String _sanitizeForKeywords(String name) { | 1622 String _sanitizeForKeywords(String name) { |
| 1633 if (jsReserved.contains(name)) { | 1623 if (jsReserved.contains(name)) { |
| 1634 name = '\$$name'; | 1624 name = '\$$name'; |
| 1635 } | 1625 } |
| 1636 assert(!jsReserved.contains(name)); | 1626 assert(!jsReserved.contains(name)); |
| 1637 return name; | 1627 return name; |
| 1638 } | 1628 } |
| 1639 | 1629 |
| 1640 jsAst.Name substitutionName(ClassElement element) { | 1630 jsAst.Name substitutionName(ClassEntity element) { |
| 1641 return new CompoundName( | 1631 return new CompoundName( |
| 1642 [new StringBackedName(operatorAsPrefix), runtimeTypeName(element)]); | 1632 [new StringBackedName(operatorAsPrefix), runtimeTypeName(element)]); |
| 1643 } | 1633 } |
| 1644 | 1634 |
| 1645 /// Translates a [String] into the corresponding [Name] data structure as | 1635 /// Translates a [String] into the corresponding [Name] data structure as |
| 1646 /// used by the namer. | 1636 /// used by the namer. |
| 1647 /// | 1637 /// |
| 1648 /// If [name] is a setter or getter name, the corresponding [GetterName] or | 1638 /// If [name] is a setter or getter name, the corresponding [GetterName] or |
| 1649 /// [SetterName] data structure is used. | 1639 /// [SetterName] data structure is used. |
| 1650 jsAst.Name asName(String name) { | 1640 jsAst.Name asName(String name) { |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2233 void addSuggestion(String original, String suggestion) { | 2223 void addSuggestion(String original, String suggestion) { |
| 2234 assert(!_suggestedNames.containsKey(original)); | 2224 assert(!_suggestedNames.containsKey(original)); |
| 2235 _suggestedNames[original] = suggestion; | 2225 _suggestedNames[original] = suggestion; |
| 2236 } | 2226 } |
| 2237 | 2227 |
| 2238 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); | 2228 bool hasSuggestion(String original) => _suggestedNames.containsKey(original); |
| 2239 bool isSuggestion(String candidate) { | 2229 bool isSuggestion(String candidate) { |
| 2240 return _suggestedNames.containsValue(candidate); | 2230 return _suggestedNames.containsValue(candidate); |
| 2241 } | 2231 } |
| 2242 } | 2232 } |
| OLD | NEW |