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

Unified Diff: pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart

Issue 2933553002: Add MemberEntity.member and refactor Emitter.getReflectionName to avoid mixin Selector and Entity (Closed)
Patch Set: Created 3 years, 6 months 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 side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index ba964c12685e45c4239be1d6cb9d720e79d204ed..9d27c4665f4668975e83966d9b29d6e5f2f6d0cc 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -21,6 +21,7 @@ import '../../deferred_load.dart' show OutputUnit;
import '../../elements/elements.dart'
show
ClassElement,
+ ConstructorBodyElement,
Element,
FieldElement,
FunctionSignature,
@@ -29,6 +30,7 @@ import '../../elements/elements.dart'
TypedefElement;
import '../../elements/entities.dart';
import '../../elements/entity_utils.dart' as utils;
+import '../../elements/names.dart';
import '../../hash/sha1.dart' show Hasher;
import '../../io/code_output.dart';
import '../../io/location_provider.dart' show LocationCollector;
@@ -405,8 +407,7 @@ class Emitter extends js_emitter.EmitterBase {
}
/// In minified mode we want to keep the name for the most common core types.
- bool _isNativeTypeNeedingReflectionName(Element element) {
- if (!element.isClass) return false;
+ bool _isNativeTypeNeedingReflectionName(ClassEntity element) {
return (element == commonElements.intClass ||
element == commonElements.doubleClass ||
element == commonElements.numClass ||
@@ -416,7 +417,35 @@ class Emitter extends js_emitter.EmitterBase {
element == commonElements.listClass);
}
- /// Returns the "reflection name" of an [Element] or [Selector].
+ /// Returns the "reflection name" of a [ClassEntity], if needed.
+ ///
+ /// The reflection name of class 'C' is 'C'.
+ /// An anonymous mixin application has no reflection name.
+ ///
+ /// This is used by js_mirrors.dart.
+ String getReflectionClassName(ClassEntity cls, jsAst.Name mangledName) {
+ String name = cls.name;
+ if (backend.mirrorsData.shouldRetainName(name) ||
+ // Make sure to retain names of common native types.
+ _isNativeTypeNeedingReflectionName(cls)) {
+ // TODO(ahe): Enable the next line when I can tell the difference between
+ // an instance method and a global. They may have the same mangled name.
+ // if (recordedMangledNames.contains(mangledName)) return null;
+ recordedMangledNames.add(mangledName);
+ if (cls.isClosure) {
+ // Closures are synthesized and their name might conflict with existing
+ // globals. Assign an illegal name, and make sure they don't clash
+ // with each other.
+ return " $name";
+ }
+ if (_elementEnvironment.isUnnamedMixinApplication(cls)) return null;
+ return cls.name;
+ }
+ return null;
+ }
+
+ /// Returns the "reflection name" of a [MemberEntity], if needed.
+ ///
/// The reflection name of a getter 'foo' is 'foo'.
/// The reflection name of a setter 'foo' is 'foo='.
/// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
@@ -424,100 +453,124 @@ class Emitter extends js_emitter.EmitterBase {
/// O is the named arguments.
/// The reflection name of a constructor is similar to a regular method but
/// starts with 'new '.
- /// The reflection name of class 'C' is 'C'.
- /// An anonymous mixin application has no reflection name.
+ ///
/// This is used by js_mirrors.dart.
- String getReflectionName(elementOrSelector, jsAst.Name mangledName) {
- String name = elementOrSelector.name;
+ String getReflectionMemberName(MemberEntity member, jsAst.Name mangledName) {
+ String name = member.name;
if (backend.mirrorsData.shouldRetainName(name) ||
- elementOrSelector is Element &&
- // Make sure to retain names of unnamed constructors, and
- // for common native types.
- ((name == '' &&
- backend.mirrorsData
- .isAccessibleByReflection(elementOrSelector)) ||
- _isNativeTypeNeedingReflectionName(elementOrSelector))) {
+ // Make sure to retain names of unnamed constructors.
+ (name == '' &&
+ backend.mirrorsData.isMemberAccessibleByReflection(member))) {
// TODO(ahe): Enable the next line when I can tell the difference between
// an instance method and a global. They may have the same mangled name.
// if (recordedMangledNames.contains(mangledName)) return null;
recordedMangledNames.add(mangledName);
- return getReflectionNameInternal(elementOrSelector, mangledName);
+ return getReflectionMemberNameInternal(member, mangledName);
}
return null;
}
- String getReflectionNameInternal(elementOrSelector, jsAst.Name mangledName) {
- String name = namer.privateName(elementOrSelector.memberName);
- if (elementOrSelector.isGetter) return name;
- if (elementOrSelector.isSetter) {
- if (mangledName is! SetterName) return '$name=';
- SetterName setterName = mangledName;
- jsAst.Name base = setterName.base;
- jsAst.Name getter = namer.deriveGetterName(base);
- mangledFieldNames.putIfAbsent(getter, () => name);
- assert(mangledFieldNames[getter] == name);
- recordedMangledNames.add(getter);
- // TODO(karlklose,ahe): we do not actually need to store information
- // about the name of this setter in the output, but it is needed for
- // marking the function as invokable by reflection.
- return '$name=';
+ String getReflectionMemberNameInternal(
+ MemberEntity member, jsAst.Name mangledName) {
+ if (member is ConstructorBodyElement) {
+ return null;
}
- if (elementOrSelector is Element && elementOrSelector.isClosure) {
- // Closures are synthesized and their name might conflict with existing
- // globals. Assign an illegal name, and make sure they don't clash
- // with each other.
- return " $name";
+ if (member.isGetter) {
+ return _getReflectionGetterName(member.memberName);
+ } else if (member.isSetter) {
+ return _getReflectionSetterName(member.memberName, mangledName);
+ } else if (member.isConstructor) {
+ ConstructorEntity constructor = member;
+ String name = utils.reconstructConstructorName(constructor);
+ return _getReflectionCallStructureName(
+ name, constructor.parameterStructure.callStructure);
+ } else if (member.isFunction) {
+ FunctionEntity function = member;
+ return _getReflectionFunctionName(
+ member.memberName, function.parameterStructure.callStructure);
}
- if (elementOrSelector is Selector ||
- elementOrSelector.isFunction ||
- elementOrSelector.isConstructor) {
- int positionalParameterCount;
- String namedArguments = '';
- bool isConstructor = false;
- if (elementOrSelector is Selector) {
- CallStructure callStructure = elementOrSelector.callStructure;
- positionalParameterCount = callStructure.positionalArgumentCount;
- namedArguments = namedParametersAsReflectionNames(callStructure);
+ throw reporter.internalError(
+ member, 'Do not know how to reflect on this $member.');
+ }
+
+ /// Returns the "reflection name" of a [Selector], if needed.
+ ///
+ /// The reflection name of a getter 'foo' is 'foo'.
+ /// The reflection name of a setter 'foo' is 'foo='.
+ /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
+ /// number of required arguments, M is the number of optional arguments, and
+ /// O is the named arguments.
+ ///
+ /// This is used by js_mirrors.dart.
+ String getReflectionSelectorName(Selector selector, jsAst.Name mangledName) {
+ String name = selector.name;
+ if (backend.mirrorsData.shouldRetainName(name)) {
+ // TODO(ahe): Enable the next line when I can tell the difference between
+ // an instance method and a global. They may have the same mangled name.
+ // if (recordedMangledNames.contains(mangledName)) return null;
+ recordedMangledNames.add(mangledName);
+ if (selector.isGetter) {
+ return _getReflectionGetterName(selector.memberName);
+ } else if (selector.isSetter) {
+ return _getReflectionSetterName(selector.memberName, mangledName);
} else {
- MethodElement function = elementOrSelector;
- if (function.isConstructor) {
- isConstructor = true;
- name = utils.reconstructConstructorName(function);
- }
- FunctionSignature signature = function.functionSignature;
- positionalParameterCount = signature.requiredParameterCount;
- if (signature.optionalParametersAreNamed) {
- var names = [];
- for (Element e in signature.optionalParameters) {
- names.add(e.name);
- }
- CallStructure callStructure =
- new CallStructure(positionalParameterCount, names);
- namedArguments = namedParametersAsReflectionNames(callStructure);
- } else {
- // Named parameters are handled differently by mirrors. For unnamed
- // parameters, they are actually required if invoked
- // reflectively. Also, if you have a method c(x) and c([x]) they both
- // get the same mangled name, so they must have the same reflection
- // name.
- positionalParameterCount += signature.optionalParameterCount;
- }
+ return _getReflectionFunctionName(
+ selector.memberName, selector.callStructure);
}
- String suffix = '$name:$positionalParameterCount$namedArguments';
- return (isConstructor) ? 'new $suffix' : suffix;
}
- Element element = elementOrSelector;
- if (element.isGenerativeConstructorBody) {
- return null;
- } else if (element.isClass) {
- ClassElement cls = element;
- if (cls.isUnnamedMixinApplication) return null;
- return cls.name;
- } else if (element.isTypedef) {
- return element.name;
+ return null;
+ }
+
+ /// Returns the "reflection name" of a [TypedefElement], if needed.
+ ///
+ /// The reflection name of typedef 'F' is 'F'.
+ ///
+ /// This is used by js_mirrors.dart.
+ String getReflectionTypedefName(
+ TypedefElement typedef, jsAst.Name mangledName) {
+ String name = typedef.name;
+ if (backend.mirrorsData.shouldRetainName(name)) {
+ // TODO(ahe): Enable the next line when I can tell the difference between
+ // an instance method and a global. They may have the same mangled name.
+ // if (recordedMangledNames.contains(mangledName)) return null;
+ recordedMangledNames.add(mangledName);
+ return typedef.name;
}
- throw reporter.internalError(
- element, 'Do not know how to reflect on this $element.');
+ return null;
+ }
+
+ String _getReflectionGetterName(Name memberName) {
+ return namer.privateName(memberName);
+ }
+
+ String _getReflectionSetterName(Name memberName, jsAst.Name mangledName) {
+ String name = namer.privateName(memberName);
+ if (mangledName is! SetterName) return '$name=';
+ SetterName setterName = mangledName;
+ jsAst.Name base = setterName.base;
+ jsAst.Name getter = namer.deriveGetterName(base);
+ mangledFieldNames.putIfAbsent(getter, () => name);
+ assert(mangledFieldNames[getter] == name);
+ recordedMangledNames.add(getter);
+ // TODO(karlklose,ahe): we do not actually need to store information
+ // about the name of this setter in the output, but it is needed for
+ // marking the function as invokable by reflection.
+ return '$name=';
+ }
+
+ String _getReflectionFunctionName(
+ Name memberName, CallStructure callStructure) {
+ String name = namer.privateName(memberName);
+ return _getReflectionCallStructureName(name, callStructure);
+ }
+
+ String _getReflectionCallStructureName(
+ String name, CallStructure callStructure,
+ {bool isConstructor: false}) {
+ int positionalParameterCount = callStructure.positionalArgumentCount;
+ String namedArguments = namedParametersAsReflectionNames(callStructure);
+ String suffix = '$name:$positionalParameterCount$namedArguments';
+ return isConstructor ? 'new $suffix' : suffix;
}
String namedParametersAsReflectionNames(CallStructure structure) {
@@ -1133,7 +1186,7 @@ class Emitter extends js_emitter.EmitterBase {
builder.superName = namer.className(commonElements.objectClass);
jsAst.Node declaration = builder.toObjectInitializer();
jsAst.Name mangledName = namer.globalPropertyNameForType(typedef);
- String reflectionName = getReflectionName(typedef, mangledName);
+ String reflectionName = getReflectionTypedefName(typedef, mangledName);
getLibraryDescriptor(library, mainFragment)
..addProperty(mangledName, declaration)
..addPropertyByName("+$reflectionName", js.string(''));

Powered by Google App Engine
This is Rietveld 408576698