@@ -110,7 +110,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
110
110
if (unit.directives.isNotEmpty) {
111
111
var libraryDir = unit.directives.first;
112
112
if (libraryDir is LibraryDirective ) {
113
- var jsName = getAnnotationValue (libraryDir, _isJsNameAnnotation);
113
+ var jsName = findNodeAnnotation (libraryDir, _isJsNameAnnotation);
114
114
jsDefaultValue = getConstantField (jsName, 'name' , types.stringType);
115
115
}
116
116
}
@@ -329,7 +329,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
329
329
// If we've already emitted this class, skip it.
330
330
var classElem = node.element;
331
331
var type = classElem.type;
332
- var jsName = getAnnotationValue (node, _isJsNameAnnotation);
332
+ var jsName = findNodeAnnotation (node, _isJsNameAnnotation);
333
333
334
334
if (jsName != null ) return _emitJsType (node.name.name, jsName);
335
335
@@ -350,7 +350,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
350
350
_classHeritage (classElem), _emitClassMethods (node, ctors, fields));
351
351
352
352
String jsPeerName;
353
- var jsPeer = getAnnotationValue (node, _isJsPeerInterface);
353
+ var jsPeer = findNodeAnnotation (node, _isJsPeerInterface);
354
354
if (jsPeer != null ) {
355
355
jsPeerName = getConstantField (jsPeer, 'name' , types.stringType);
356
356
}
@@ -475,7 +475,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
475
475
jsMethods.add (_emitImplicitConstructor (node, fields));
476
476
}
477
477
478
- bool hasJsPeer = getAnnotationValue (node, _isJsPeerInterface) != null ;
478
+ bool hasJsPeer = findNodeAnnotation (node, _isJsPeerInterface) != null ;
479
479
480
480
bool hasIterator = false ;
481
481
for (var m in node.members) {
@@ -1349,7 +1349,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
1349
1349
1350
1350
JS .Expression _emitSet (Expression lhs, Expression rhs) {
1351
1351
if (lhs is IndexExpression ) {
1352
- return _emitSend (_getTarget (lhs), '[]=' , [lhs.index, rhs]);
1352
+ var target = _getTarget (lhs);
1353
+ if (_useNativeJsIndexer (target.staticType)) {
1354
+ return js.call (
1355
+ '#[#] = #' , [_visit (target), _visit (lhs.index), _visit (rhs)]);
1356
+ }
1357
+ return _emitSend (target, '[]=' , [lhs.index, rhs]);
1353
1358
}
1354
1359
1355
1360
Expression target = null ;
@@ -2116,9 +2121,18 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
2116
2121
2117
2122
@override
2118
2123
visitIndexExpression (IndexExpression node) {
2119
- return _emitSend (_getTarget (node), '[]' , [node.index]);
2124
+ var target = _getTarget (node);
2125
+ if (_useNativeJsIndexer (target.staticType)) {
2126
+ return new JS .PropertyAccess (_visit (target), _visit (node.index));
2127
+ }
2128
+ return _emitSend (target, '[]' , [node.index]);
2120
2129
}
2121
2130
2131
+ // TODO(jmesserly): ideally we'd check the method and see if it is marked
2132
+ // `external`, but that doesn't work because it isn't in the element model.
2133
+ bool _useNativeJsIndexer (DartType type) =>
2134
+ findElementAnnotation (type.element, _isJsIndexerAnnotation) != null ;
2135
+
2122
2136
/// Gets the target of a [PropertyAccess] or [IndexExpression] .
2123
2137
/// Those two nodes are special because they're both allowed on left side of
2124
2138
/// an assignment expression and cascades.
@@ -2636,6 +2650,9 @@ String jsOutputPath(LibraryInfo info, Uri root) {
2636
2650
// TODO(jmesserly): validate the library. See issue #135.
2637
2651
bool _isJsNameAnnotation (DartObjectImpl value) => value.type.name == 'JsName' ;
2638
2652
2653
+ bool _isJsIndexerAnnotation (DartObjectImpl value) =>
2654
+ value.type.name == 'JsIndexer' ;
2655
+
2639
2656
bool _isJsPeerInterface (DartObjectImpl value) =>
2640
2657
value.type.name == 'JsPeerInterface' ;
2641
2658
0 commit comments