Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 3038a2b

Browse files
committed
Support call methods on functions
Fixes #624 R=jmesserly@google.com Review URL: https://codereview.chromium.org/2255993002 .
1 parent 0189013 commit 3038a2b

File tree

3 files changed

+69
-12
lines changed

3 files changed

+69
-12
lines changed

lib/src/compiler/code_generator.dart

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3180,6 +3180,19 @@ class CodeGenerator extends GeneralizingAstVisitor
31803180
if (target == null || isLibraryPrefix(target)) {
31813181
return _emitFunctionCall(node);
31823182
}
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 || targetType.isDynamic) {
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+
}
31833196

31843197
return _emitMethodCall(target, node);
31853198
}
@@ -3273,22 +3286,27 @@ class CodeGenerator extends GeneralizingAstVisitor
32733286
return new JS.Call(jsTarget, args);
32743287
}
32753288

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+
32763303
/// Emits a function call, to a top-level function, local function, or
32773304
/// an expression.
32783305
JS.Expression _emitFunctionCall(InvocationExpression node) {
32793306
var fn = _visit(node.function);
32803307
var args = _visit(node.argumentList) as List<JS.Expression>;
32813308
if (isDynamicInvoke(node.function)) {
3282-
var typeArgs = _emitInvokeTypeArguments(node);
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-
}
3309+
return _emitDynamicInvoke(node, fn, args);
32923310
} else {
32933311
return new JS.Call(_applyInvokeTypeArguments(fn, node), args);
32943312
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import "package:expect/expect.dart";
6+
7+
Object bar(Object x) { return x; }
8+
9+
Function baz = bar;
10+
11+
dynamic dyn = bar;
12+
13+
class Foo {
14+
Object call(Object x) { return 'Foo$x'; }
15+
}
16+
17+
typedef Object FooType(Object x);
18+
FooType foo = bar;
19+
20+
void main() {
21+
Expect.equals(42, bar.call(42));
22+
Expect.equals(42, baz.call(42));
23+
Expect.equals(42, foo.call(42));
24+
Expect.equals(42, dyn.call(42));
25+
Expect.equals(42, bar(42));
26+
Expect.equals(42, baz(42));
27+
Expect.equals(42, foo(42));
28+
Expect.equals(42, dyn(42));
29+
30+
baz = new Foo();
31+
foo = new Foo();
32+
dyn = new Foo();
33+
Expect.equals('Foo42', baz.call(42));
34+
Expect.equals('Foo42', foo.call(42));
35+
Expect.equals('Foo42', dyn.call(42));
36+
Expect.equals('Foo42', baz(42));
37+
Expect.equals('Foo42', foo(42));
38+
Expect.equals('Foo42', dyn(42));
39+
}

test/codegen_expected/varargs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ dart_library.library('varargs', null, /* Imports */[
1111
let dynamicTodynamic = () => (dynamicTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [dart.dynamic])))();
1212
varargs.varargsTest = function(x, ...others) {
1313
let args = [1, others];
14-
dart.dsend(x, 'call', ...args);
14+
dart.dcall(x, ...args);
1515
};
1616
dart.fn(varargs.varargsTest, dynamicAnddynamicTodynamic());
1717
varargs.varargsTest2 = function(x, ...others) {
1818
let args = [1, others];
19-
dart.dsend(x, 'call', ...args);
19+
dart.dcall(x, ...args);
2020
};
2121
dart.fn(varargs.varargsTest2, dynamicAnddynamicTodynamic());
2222
src__varargs._Rest = class _Rest extends core.Object {

0 commit comments

Comments
 (0)