Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart |
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
index 361f5ec0198127d03ab3f0f684ebeaa356228e5d..24fc526734ba6e9979bd19f7997e3042faf858b8 100644 |
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
@@ -324,11 +324,8 @@ class CodeGenerator extends GeneralizingAstVisitor |
elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; |
} |
- if (e is TopLevelVariableElement && |
- e.getter != null && |
- (e.getter.isExternal || |
- findAnnotation(e.getter, isPublicJSAnnotation) != null)) { |
- elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? ''; |
+ if (e is TopLevelVariableElement) { |
+ elementJSName = _jsInteropStaticMemberName(e); |
} |
if (elementJSName == null) return null; |
@@ -353,6 +350,33 @@ class CodeGenerator extends GeneralizingAstVisitor |
return access; |
} |
+ String _jsInteropStaticMemberName(Element e, {String name}) { |
+ if (e == null || e.library == null || |
+ findAnnotation(e.library, isPublicJSAnnotation) == null) { |
+ return null; |
+ } |
+ if (e is PropertyInducingElement) { |
+ // Assume properties have consistent JS names for getters and setters. |
+ return _jsInteropStaticMemberName(e.getter, name: e.name) ?? |
+ _jsInteropStaticMemberName(e.setter, name: e.name); |
+ } |
+ if (e is ExecutableElement && |
+ e.isExternal && |
+ findAnnotation(e, isPublicJSAnnotation) != null) { |
+ return getAnnotationName(e, isPublicJSAnnotation) ?? name ?? e.name; |
+ } |
+ return null; |
+ } |
+ |
+ JS.Expression _emitJSInteropStaticMemberName(Element e) { |
+ var name = _jsInteropStaticMemberName(e); |
+ if (name == null) return null; |
+ // We do not support statics names with JS annotations containing dots. |
+ // See https://github.com/dart-lang/sdk/issues/27926 |
+ assert(!name.contains('.')); |
Jennifer Messerly
2016/11/29 20:54:52
This should be an error or a throw, rather than an
Jacob
2016/11/29 21:37:33
Done.
|
+ return js.string(name); |
+ } |
+ |
/// Flattens blocks in [items] to a single list. |
/// |
/// This will not flatten blocks that are marked as being scopes. |
@@ -2705,7 +2729,8 @@ class CodeGenerator extends GeneralizingAstVisitor |
if (element is ClassMemberElement && element is! ConstructorElement) { |
bool isStatic = element.isStatic; |
var type = element.enclosingElement.type; |
- var member = _emitMemberName(name, isStatic: isStatic, type: type); |
+ var member = _emitMemberName(name, |
+ isStatic: isStatic, type: type, element: element); |
if (isStatic) { |
var dynType = _emitStaticAccess(type); |
@@ -3271,7 +3296,8 @@ class CodeGenerator extends GeneralizingAstVisitor |
ClassElement classElement = element.enclosingElement; |
var type = classElement.type; |
var dynType = _emitStaticAccess(type); |
- var member = _emitMemberName(element.name, isStatic: true, type: type); |
+ var member = _emitMemberName(element.name, |
+ isStatic: true, type: type, element: element); |
return _visit(rhs).toAssignExpression( |
annotate(new JS.PropertyAccess(dynType, member), lhs)); |
} |
@@ -3282,7 +3308,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
JS.Expression jsTarget, Element element, JS.Expression value) { |
String memberName = element.name; |
var type = (element.enclosingElement as ClassElement).type; |
- var name = _emitMemberName(memberName, type: type); |
+ var name = _emitMemberName(memberName, type: type, element: element); |
return value.toAssignExpression( |
annotate(new JS.PropertyAccess(jsTarget, name), lhs)); |
} |
@@ -3430,21 +3456,28 @@ class CodeGenerator extends GeneralizingAstVisitor |
return _emitStaticAccess( |
(element.enclosingElement as ClassElement).type); |
} |
+ if (element is FieldElement) { |
+ var enclosingElement = element.enclosingElement; |
+ if (enclosingElement is ClassElement) { |
Jennifer Messerly
2016/11/29 20:54:52
the "is" check is unnecessary -- FieldElement is a
Jacob
2016/11/29 21:37:33
Surprised I ever thought that is check was needed.
|
+ return _emitStaticAccess(enclosingElement.type); |
+ } |
+ } |
} |
return _visit(target); |
} |
- /// Emits a (possibly generic) instance method call. |
+ /// Emits a (possibly generic) instance, or static method call. |
JS.Expression _emitMethodCallInternal( |
Expression target, |
MethodInvocation node, |
List<JS.Expression> args, |
List<JS.Expression> typeArgs) { |
var type = getStaticType(target); |
- var name = node.methodName.name; |
var element = node.methodName.staticElement; |
bool isStatic = element is ExecutableElement && element.isStatic; |
- var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
+ var name = node.methodName.name; |
+ var memberName = |
+ _emitMemberName(name, type: type, isStatic: isStatic, element: element); |
JS.Expression jsTarget = _emitTarget(target, element, isStatic); |
if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { |
@@ -4807,7 +4840,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
String memberName, List<JS.Expression> typeArgs) { |
bool isStatic = member is ClassMemberElement && member.isStatic; |
var name = _emitMemberName(memberName, |
- type: getStaticType(target), isStatic: isStatic); |
+ type: getStaticType(target), isStatic: isStatic, element: member); |
if (isDynamicInvoke(target)) { |
if (_inWhitelistCode(target)) { |
var vars = <JS.MetaLetVariable, JS.Expression>{}; |
@@ -5426,9 +5459,14 @@ class CodeGenerator extends GeneralizingAstVisitor |
/// helper, that checks for null. The user defined method is called '=='. |
/// |
JS.Expression _emitMemberName(String name, |
- {DartType type, bool isStatic: false, bool useExtension}) { |
- // Static members skip the rename steps. |
- if (isStatic) return _propertyName(name); |
+ {DartType type, |
+ bool isStatic: false, |
+ bool useExtension, |
+ Element element}) { |
+ // Static members skip the rename steps and may require JS interop renames. |
+ if (isStatic) { |
+ return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); |
+ } |
if (name.startsWith('_')) { |
return _emitPrivateNameSymbol(currentLibrary, name); |