Index: pkg/compiler/lib/src/js_backend/namer.dart |
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart |
index 26dd37605963a441cf14f8e5ab68a69565dfa0d9..78966e3d53a6377f8f0ba3dbbae4f16b52a515d3 100644 |
--- a/pkg/compiler/lib/src/js_backend/namer.dart |
+++ b/pkg/compiler/lib/src/js_backend/namer.dart |
@@ -370,7 +370,7 @@ class Namer { |
/// Although global names are distributed across a number of global objects, |
/// (see [globalObjectFor]), we currently use a single namespace for all these |
/// names. |
- final Set<String> usedGlobalNames = new Set<String>(); |
+ final NamingScope globalScope = new NamingScope(); |
final Map<Element, jsAst.Name> userGlobals = |
new HashMap<Element, jsAst.Name>(); |
final Map<String, jsAst.Name> internalGlobals = |
@@ -379,7 +379,7 @@ class Namer { |
/// Used disambiguated names in the instance namespace, issued by |
/// [_disambiguateMember], [_disambiguateInternalMember], |
/// [_disambiguateOperator], and [reservePublicMemberName]. |
- final Set<String> usedInstanceNames = new Set<String>(); |
+ final NamingScope instanceScope = new NamingScope(); |
final Map<String, jsAst.Name> userInstanceMembers = |
new HashMap<String, jsAst.Name>(); |
final Map<Element, jsAst.Name> internalInstanceMembers = |
@@ -388,18 +388,11 @@ class Namer { |
new HashMap<String, jsAst.Name>(); |
/// Used to disambiguate names for constants in [constantName]. |
- final Set<String> usedConstantNames = new Set<String>(); |
+ final NamingScope constantScope = new NamingScope(); |
- Set<String> getUsedNames(NamingScope scope) { |
- if (scope == NamingScope.global) { |
- return usedGlobalNames; |
- } else if (scope == NamingScope.instance){ |
- return usedInstanceNames; |
- } else { |
- assert(scope == NamingScope.constant); |
- return usedConstantNames; |
- } |
- } |
+ /// Used to store scopes for instances of [PrivatelyNamedJsEntity] |
+ final Map<Entity, NamingScope> _privateNamingScopes = |
+ new Map<Entity, NamingScope>(); |
final Map<String, int> popularNameCounters = <String, int>{}; |
@@ -417,28 +410,9 @@ class Namer { |
final Map<String, LibraryElement> shortPrivateNameOwners = |
<String, LibraryElement>{}; |
- /// Maps proposed names to *suggested* disambiguated names. |
- /// |
- /// Suggested names are hints to the [MinifyNamer], suggesting that a specific |
- /// names be given to the first item with the given proposed name. |
- /// |
- /// This is currently used in [MinifyNamer] to assign very short minified |
- /// names to things that tend to be used very often. |
final Map<String, String> suggestedGlobalNames = <String, String>{}; |
final Map<String, String> suggestedInstanceNames = <String, String>{}; |
- Map<String, String> getSuggestedNames(NamingScope scope) { |
- if (scope == NamingScope.global) { |
- return suggestedGlobalNames; |
- } else if (scope == NamingScope.instance) { |
- return suggestedInstanceNames; |
- } else { |
- assert(scope == NamingScope.constant); |
- return const {}; |
- } |
- } |
- |
- |
/// Used to store unique keys for library names. Keys are not used as names, |
/// nor are they visible in the output. The only serve as an internal |
/// key into maps. |
@@ -476,6 +450,11 @@ class Namer { |
String get closureInvocationSelectorName => Identifiers.call; |
bool get shouldMinify => false; |
+ NamingScope _getPrivateScopeFor(PrivatelyNamedJSEntity entity) { |
+ return _privateNamingScopes.putIfAbsent(entity.rootOfScope, |
+ () => new NamingScope()); |
+ } |
+ |
/// Returns the string that is to be used as the result of a call to |
/// [JS_GET_NAME] at [node] with argument [name]. |
jsAst.Name getNameForJsGetName(Node node, JsGetName name) { |
@@ -545,7 +524,7 @@ class Namer { |
jsAst.Name result = constantNames[constant]; |
if (result == null) { |
String longName = constantLongName(constant); |
- result = getFreshName(NamingScope.constant, longName); |
+ result = getFreshName(constantScope, longName); |
constantNames[constant] = result; |
} |
return _newReference(result); |
@@ -799,14 +778,16 @@ class Namer { |
return new StringBackedName(backend.getFixedBackendName(element)); |
} |
- // Instances of BoxFieldElement are special. They are already created with |
- // a unique and safe name. However, as boxes are not really instances of |
- // classes, the usual naming scheme that tries to avoid name clashes with |
- // super classes does not apply. We still do not mark the name as a |
- // fixedBackendName, as we want to allow other namers to do something more |
- // clever with them. |
- if (element is BoxFieldElement) { |
- return new StringBackedName(element.name); |
+ // Some elements, like e.g. instances of BoxFieldElement are special. |
+ // They are created with a unique and safe name for the element model. |
+ // While their name is unique, it is not very readable. So we try to |
+ // preserve the original, proposed name. |
+ // However, as boxes are not really instances of classes, the usual naming |
+ // scheme that tries to avoid name clashes with super classes does not |
+ // apply. So we can directly grab a name. |
+ if (element is JSEntity) { |
+ return _disambiguateInternalMember(element, |
+ () => element.declaredEntity.name); |
} |
// If the name of the field might clash with another field, |
@@ -882,7 +863,7 @@ class Namer { |
jsAst.Name _disambiguateInternalGlobal(String name) { |
jsAst.Name newName = internalGlobals[name]; |
if (newName == null) { |
- newName = getFreshName(NamingScope.global, name); |
+ newName = getFreshName(globalScope, name); |
internalGlobals[name] = newName; |
} |
return _newReference(newName); |
@@ -929,7 +910,7 @@ class Namer { |
jsAst.Name newName = userGlobals[element]; |
if (newName == null) { |
String proposedName = _proposeNameForGlobal(element); |
- newName = getFreshName(NamingScope.global, proposedName); |
+ newName = getFreshName(globalScope, proposedName); |
userGlobals[element] = newName; |
} |
return _newReference(newName); |
@@ -969,7 +950,7 @@ class Namer { |
// proposed name must be a valid identifier, but not necessarily unique. |
proposedName += r'$' + suffixes.join(r'$'); |
} |
- newName = getFreshName(NamingScope.instance, proposedName, |
+ newName = getFreshName(instanceScope, proposedName, |
sanitizeForAnnotations: true); |
userInstanceMembers[key] = newName; |
} |
@@ -992,7 +973,7 @@ class Namer { |
jsAst.Name newName = userInstanceMembers[key]; |
if (newName == null) { |
String name = proposeName(); |
- newName = getFreshName(NamingScope.instance, name, |
+ newName = getFreshName(instanceScope, name, |
sanitizeForAnnotations: true); |
userInstanceMembers[key] = newName; |
} |
@@ -1014,9 +995,9 @@ class Namer { |
String suffix = ''; // We don't need any suffixes. |
String key = '$libraryPrefix@$originalName@$suffix'; |
assert(!userInstanceMembers.containsKey(key)); |
- assert(!usedInstanceNames.contains(disambiguatedName)); |
+ assert(!instanceScope.isUsed(disambiguatedName)); |
userInstanceMembers[key] = new StringBackedName(disambiguatedName); |
- usedInstanceNames.add(disambiguatedName); |
+ instanceScope.registerUse(disambiguatedName); |
} |
/// Disambiguated name unique to [element]. |
@@ -1030,11 +1011,21 @@ class Namer { |
jsAst.Name newName = internalInstanceMembers[element]; |
if (newName == null) { |
String name = proposeName(); |
- bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass); |
- newName = getFreshName(NamingScope.instance, name, |
- sanitizeForAnnotations: true, |
- sanitizeForNatives: mayClashNative); |
- internalInstanceMembers[element] = newName; |
+ |
+ if (element is PrivatelyNamedJSEntity) { |
+ NamingScope scope = _getPrivateScopeFor(element); |
+ newName = getFreshName(scope, name, |
+ sanitizeForAnnotations: true, |
+ sanitizeForNatives: false); |
+ internalInstanceMembers[element] = newName; |
+ } else { |
+ bool mayClashNative = |
+ _isUserClassExtendingNative(element.enclosingClass); |
+ newName = getFreshName(instanceScope, name, |
+ sanitizeForAnnotations: true, |
+ sanitizeForNatives: mayClashNative); |
+ internalInstanceMembers[element] = newName; |
+ } |
} |
return _newReference(newName); |
} |
@@ -1048,15 +1039,14 @@ class Namer { |
jsAst.Name _disambiguateOperator(String operatorIdentifier) { |
jsAst.Name newName = userInstanceOperators[operatorIdentifier]; |
if (newName == null) { |
- newName = getFreshName(NamingScope.instance, operatorIdentifier); |
+ newName = getFreshName(instanceScope, operatorIdentifier); |
userInstanceOperators[operatorIdentifier] = newName; |
} |
return _newReference(newName); |
} |
String _generateFreshStringForName(String proposedName, |
- Set<String> usedNames, |
- Map<String, String> suggestedNames, |
+ NamingScope scope, |
{bool sanitizeForAnnotations: false, |
bool sanitizeForNatives: false}) { |
if (sanitizeForAnnotations) { |
@@ -1067,18 +1057,18 @@ class Namer { |
} |
proposedName = _sanitizeForKeywords(proposedName); |
String candidate; |
- if (!usedNames.contains(proposedName)) { |
+ if (scope.isUnused(proposedName)) { |
candidate = proposedName; |
} else { |
int counter = popularNameCounters[proposedName]; |
int i = (counter == null) ? 0 : counter; |
- while (usedNames.contains("$proposedName$i")) { |
+ while (scope.isUsed("$proposedName$i")) { |
i++; |
} |
popularNameCounters[proposedName] = i + 1; |
candidate = "$proposedName$i"; |
} |
- usedNames.add(candidate); |
+ scope.registerUse(candidate); |
return candidate; |
} |
@@ -1100,8 +1090,7 @@ class Namer { |
bool sanitizeForNatives: false}) { |
String candidate = |
_generateFreshStringForName(proposedName, |
- getUsedNames(scope), |
- getSuggestedNames(scope), |
+ scope, |
sanitizeForAnnotations: |
sanitizeForAnnotations, |
sanitizeForNatives: sanitizeForNatives); |
@@ -1436,7 +1425,7 @@ class Namer { |
jsAst.Name getFunctionTypeName(FunctionType functionType) { |
return functionTypeNameMap.putIfAbsent(functionType, () { |
String proposedName = functionTypeNamer.computeName(functionType); |
- return getFreshName(NamingScope.instance, proposedName); |
+ return getFreshName(instanceScope, proposedName); |
}); |
} |
@@ -1572,7 +1561,6 @@ class Namer { |
void forgetElement(Element element) { |
jsAst.Name globalName = userGlobals[element]; |
invariant(element, globalName != null, message: 'No global name.'); |
- usedGlobalNames.remove(globalName); |
userGlobals.remove(element); |
} |
} |
@@ -2028,8 +2016,29 @@ class FunctionTypeNamer extends BaseDartTypeVisitor { |
} |
} |
-enum NamingScope { |
- global, |
- instance, |
- constant |
+ |
+class NamingScope { |
+ /// Maps proposed names to *suggested* disambiguated names. |
+ /// |
+ /// Suggested names are hints to the [MinifyNamer], suggesting that a specific |
+ /// names be given to the first item with the given proposed name. |
+ /// |
+ /// This is currently used in [MinifyNamer] to assign very short minified |
+ /// names to things that tend to be used very often. |
+ final Map<String, String> _suggestedNames = new Map<String, String>(); |
+ final Set<String> _usedNames = new Set<String>(); |
+ |
+ bool isUsed(String name) => _usedNames.contains(name); |
+ bool isUnused(String name) => !_usedNames.contains(name); |
+ bool registerUse(String name) => _usedNames.add(name); |
+ |
+ String suggestName(String original) => _suggestedNames[original]; |
+ void addSuggestion(String original, String suggestion) { |
+ assert(!_suggestedNames.containsKey(original)); |
+ _suggestedNames[original] = suggestion; |
+ } |
+ bool hasSuggestion(String original) => _suggestedNames.containsKey(original); |
+ bool isSuggestion(String candidate) { |
+ return _suggestedNames.containsValue(candidate); |
+ } |
} |