OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
6 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
7 | 7 |
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
(...skipping 3162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3173 return _emitNullSafe(node); | 3173 return _emitNullSafe(node); |
3174 } | 3174 } |
3175 | 3175 |
3176 var result = _emitForeignJS(node); | 3176 var result = _emitForeignJS(node); |
3177 if (result != null) return result; | 3177 if (result != null) return result; |
3178 | 3178 |
3179 var target = _getTarget(node); | 3179 var target = _getTarget(node); |
3180 if (target == null || isLibraryPrefix(target)) { | 3180 if (target == null || isLibraryPrefix(target)) { |
3181 return _emitFunctionCall(node); | 3181 return _emitFunctionCall(node); |
3182 } | 3182 } |
| 3183 if (node.methodName.name == 'call') { |
| 3184 var targetType = target.staticType; |
| 3185 if (targetType is FunctionType) { |
| 3186 // Call methods on function types should be handled as regular function |
| 3187 // invocations. |
| 3188 return _emitFunctionCall(node); |
| 3189 } |
| 3190 if (targetType.isDartCoreFunction) { |
| 3191 // TODO(vsm): Can a call method take generic type parameters? |
| 3192 return _emitDynamicInvoke(node, _visit(target), |
| 3193 _visit(node.argumentList) as List<JS.Expression>); |
| 3194 } |
| 3195 } |
3183 | 3196 |
3184 return _emitMethodCall(target, node); | 3197 return _emitMethodCall(target, node); |
3185 } | 3198 } |
3186 | 3199 |
3187 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { | 3200 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { |
3188 var args = _visit(node.argumentList) as List<JS.Expression>; | 3201 var args = _visit(node.argumentList) as List<JS.Expression>; |
3189 var typeArgs = _emitInvokeTypeArguments(node); | 3202 var typeArgs = _emitInvokeTypeArguments(node); |
3190 | 3203 |
3191 if (target is SuperExpression && !_superAllowed) { | 3204 if (target is SuperExpression && !_superAllowed) { |
3192 return _emitSuperHelperCall(typeArgs, args, target, node); | 3205 return _emitSuperHelperCall(typeArgs, args, target, node); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 assert(typeArgs == null); // Object methods don't take type args. | 3279 assert(typeArgs == null); // Object methods don't take type args. |
3267 return js.call('dart.#(#, #)', [name, jsTarget, args]); | 3280 return js.call('dart.#(#, #)', [name, jsTarget, args]); |
3268 } | 3281 } |
3269 | 3282 |
3270 jsTarget = new JS.PropertyAccess(jsTarget, memberName); | 3283 jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
3271 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); | 3284 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
3272 | 3285 |
3273 return new JS.Call(jsTarget, args); | 3286 return new JS.Call(jsTarget, args); |
3274 } | 3287 } |
3275 | 3288 |
| 3289 JS.Expression _emitDynamicInvoke( |
| 3290 InvocationExpression node, JS.Expression fn, List<JS.Expression> args) { |
| 3291 var typeArgs = _emitInvokeTypeArguments(node); |
| 3292 if (typeArgs != null) { |
| 3293 return js.call('dart.dgcall(#, #, #)', |
| 3294 [fn, new JS.ArrayInitializer(typeArgs), args]); |
| 3295 } else { |
| 3296 if (_inWhitelistCode(node, isCall: true)) { |
| 3297 return new JS.Call(fn, args); |
| 3298 } |
| 3299 return js.call('dart.dcall(#, #)', [fn, args]); |
| 3300 } |
| 3301 } |
| 3302 |
3276 /// Emits a function call, to a top-level function, local function, or | 3303 /// Emits a function call, to a top-level function, local function, or |
3277 /// an expression. | 3304 /// an expression. |
3278 JS.Expression _emitFunctionCall(InvocationExpression node) { | 3305 JS.Expression _emitFunctionCall(InvocationExpression node) { |
3279 var fn = _visit(node.function); | 3306 var fn = _visit(node.function); |
3280 var args = _visit(node.argumentList) as List<JS.Expression>; | 3307 var args = _visit(node.argumentList) as List<JS.Expression>; |
3281 if (isDynamicInvoke(node.function)) { | 3308 if (isDynamicInvoke(node.function)) { |
3282 var typeArgs = _emitInvokeTypeArguments(node); | 3309 return _emitDynamicInvoke(node, fn, args); |
3283 if (typeArgs != null) { | |
3284 return js.call('dart.dgcall(#, #, #)', | |
3285 [fn, new JS.ArrayInitializer(typeArgs), args]); | |
3286 } else { | |
3287 if (_inWhitelistCode(node, isCall: true)) { | |
3288 return new JS.Call(fn, args); | |
3289 } | |
3290 return js.call('dart.dcall(#, #)', [fn, args]); | |
3291 } | |
3292 } else { | 3310 } else { |
3293 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); | 3311 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); |
3294 } | 3312 } |
3295 } | 3313 } |
3296 | 3314 |
3297 JS.Expression _applyInvokeTypeArguments( | 3315 JS.Expression _applyInvokeTypeArguments( |
3298 JS.Expression target, InvocationExpression node) { | 3316 JS.Expression target, InvocationExpression node) { |
3299 var typeArgs = _emitInvokeTypeArguments(node); | 3317 var typeArgs = _emitInvokeTypeArguments(node); |
3300 if (typeArgs == null) return target; | 3318 if (typeArgs == null) return target; |
3301 return new JS.Call(target, typeArgs); | 3319 return new JS.Call(target, typeArgs); |
(...skipping 2065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5367 } | 5385 } |
5368 | 5386 |
5369 bool isLibraryPrefix(Expression node) => | 5387 bool isLibraryPrefix(Expression node) => |
5370 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5388 node is SimpleIdentifier && node.staticElement is PrefixElement; |
5371 | 5389 |
5372 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5390 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
5373 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5391 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
5374 | 5392 |
5375 bool _isDartRuntime(LibraryElement l) => | 5393 bool _isDartRuntime(LibraryElement l) => |
5376 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5394 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |