Index: lib/src/codegen/js_codegen.dart |
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart |
index 3ba321bf2cf8936668f328652fe4584bbd0bc3b7..6121f5f4a82a7c3ebca8e1e193fdfa7bacec47cf 100644 |
--- a/lib/src/codegen/js_codegen.dart |
+++ b/lib/src/codegen/js_codegen.dart |
@@ -110,7 +110,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
if (unit.directives.isNotEmpty) { |
var libraryDir = unit.directives.first; |
if (libraryDir is LibraryDirective) { |
- var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation); |
+ var jsName = findNodeAnnotation(libraryDir, _isJsNameAnnotation); |
jsDefaultValue = getConstantField(jsName, 'name', types.stringType); |
} |
} |
@@ -329,7 +329,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
// If we've already emitted this class, skip it. |
var classElem = node.element; |
var type = classElem.type; |
- var jsName = getAnnotationValue(node, _isJsNameAnnotation); |
+ var jsName = findNodeAnnotation(node, _isJsNameAnnotation); |
if (jsName != null) return _emitJsType(node.name.name, jsName); |
@@ -347,7 +347,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
_classHeritage(classElem), _emitClassMethods(node, ctors, fields)); |
String jsPeerName; |
- var jsPeer = getAnnotationValue(node, _isJsPeerInterface); |
+ var jsPeer = findNodeAnnotation(node, _isJsPeerInterface); |
if (jsPeer != null) { |
jsPeerName = getConstantField(jsPeer, 'name', types.stringType); |
} |
@@ -473,7 +473,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
jsMethods.add(_emitImplicitConstructor(node, name, fields)); |
} |
- bool hasJsPeer = getAnnotationValue(node, _isJsPeerInterface) != null; |
+ bool hasJsPeer = findNodeAnnotation(node, _isJsPeerInterface) != null; |
bool hasIterator = false; |
for (var m in node.members) { |
@@ -1184,7 +1184,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
JS.Expression _emitSet(Expression lhs, Expression rhs) { |
if (lhs is IndexExpression) { |
- return _emitSend(_getTarget(lhs), '[]=', [lhs.index, rhs]); |
+ var target = _getTarget(lhs); |
+ if (_useNativeJsIndexer(target.staticType)) { |
+ return js.call( |
+ '#[#] = #', [_visit(target), _visit(lhs.index), _visit(rhs)]); |
+ } |
+ return _emitSend(target, '[]=', [lhs.index, rhs]); |
} |
Expression target = null; |
@@ -1945,9 +1950,18 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
@override |
visitIndexExpression(IndexExpression node) { |
- return _emitSend(_getTarget(node), '[]', [node.index]); |
+ var target = _getTarget(node); |
+ if (_useNativeJsIndexer(target.staticType)) { |
+ return new JS.PropertyAccess(_visit(target), _visit(node.index)); |
+ } |
+ return _emitSend(target, '[]', [node.index]); |
} |
+ // TODO(jmesserly): ideally we'd check the method and see if it is marked |
+ // `external`, but that doesn't work because it isn't in the element model. |
+ bool _useNativeJsIndexer(DartType type) => |
+ findElementAnnotation(type.element, _isJsIndexerAnnotation) != null; |
+ |
/// Gets the target of a [PropertyAccess] or [IndexExpression]. |
/// Those two nodes are special because they're both allowed on left side of |
/// an assignment expression and cascades. |
@@ -2465,6 +2479,9 @@ String jsOutputPath(LibraryInfo info, Uri root) { |
// TODO(jmesserly): validate the library. See issue #135. |
bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
+bool _isJsIndexerAnnotation(DartObjectImpl value) => |
+ value.type.name == 'JsIndexer'; |
+ |
bool _isJsPeerInterface(DartObjectImpl value) => |
value.type.name == 'JsPeerInterface'; |