| Index: lib/src/codegen/js_codegen.dart
|
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
|
| index aeec324d59d20405ff936b7272c586e26187449f..ef02bbf709da3b353aafc253a4f6c54b093369dc 100644
|
| --- a/lib/src/codegen/js_codegen.dart
|
| +++ b/lib/src/codegen/js_codegen.dart
|
| @@ -757,9 +757,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| JS.Block visitBlock(Block node) => new JS.Block(_visitList(node.statements));
|
|
|
| @override
|
| - JS.Expression visitMethodInvocation(MethodInvocation node) {
|
| + visitMethodInvocation(MethodInvocation node) {
|
| var target = node.isCascaded ? _cascadeTarget : node.target;
|
|
|
| + var result = _emitForeignJS(node);
|
| + if (result != null) return result;
|
| +
|
| if (rules.isDynamicCall(node.methodName)) {
|
| var args = node.argumentList.accept(this);
|
| if (target != null) {
|
| @@ -787,6 +790,25 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| return js.call('#(#)', [targetJs, node.argumentList.accept(this)]);
|
| }
|
|
|
| + /// Emits code for the `JS(...)` builtin.
|
| + _emitForeignJS(MethodInvocation node) {
|
| + var e = node.methodName.staticElement;
|
| + if (e is FunctionElement &&
|
| + e.library.name == '_foreign_helper' &&
|
| + e.name == 'JS') {
|
| + var args = node.argumentList.arguments;
|
| + // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
|
| + var code = args[1] as StringLiteral;
|
| +
|
| + var template = js.parseForeignJS(code.stringValue);
|
| + var result = template.instantiate(_visitList(args.skip(2)));
|
| + // `throw` is emitted as a statement by `parseForeignJS`.
|
| + assert(result is JS.Expression || node.parent is ExpressionStatement);
|
| + return result;
|
| + }
|
| + return null;
|
| + }
|
| +
|
| @override
|
| JS.Expression visitFunctionExpressionInvocation(
|
| FunctionExpressionInvocation node) {
|
|
|