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 library ddc.src.codegen.js_codegen; | 5 library ddc.src.codegen.js_codegen; |
6 | 6 |
7 import 'dart:io' show Directory, File; | 7 import 'dart:io' show Directory, File; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 var initArgs = _emitArgumentInitializers(_parametersOf(node.parent)); | 750 var initArgs = _emitArgumentInitializers(_parametersOf(node.parent)); |
751 var block = visitBlock(node.block); | 751 var block = visitBlock(node.block); |
752 if (initArgs != null) return new JS.Block([initArgs, block]); | 752 if (initArgs != null) return new JS.Block([initArgs, block]); |
753 return block; | 753 return block; |
754 } | 754 } |
755 | 755 |
756 @override | 756 @override |
757 JS.Block visitBlock(Block node) => new JS.Block(_visitList(node.statements)); | 757 JS.Block visitBlock(Block node) => new JS.Block(_visitList(node.statements)); |
758 | 758 |
759 @override | 759 @override |
760 JS.Expression visitMethodInvocation(MethodInvocation node) { | 760 visitMethodInvocation(MethodInvocation node) { |
761 var target = node.isCascaded ? _cascadeTarget : node.target; | 761 var target = node.isCascaded ? _cascadeTarget : node.target; |
762 | 762 |
| 763 var result = _emitForeignJS(node); |
| 764 if (result != null) return result; |
| 765 |
763 if (rules.isDynamicCall(node.methodName)) { | 766 if (rules.isDynamicCall(node.methodName)) { |
764 var args = node.argumentList.accept(this); | 767 var args = node.argumentList.accept(this); |
765 if (target != null) { | 768 if (target != null) { |
766 return js.call('dart.dinvoke(#, #, #)', [ | 769 return js.call('dart.dinvoke(#, #, #)', [ |
767 target.accept(this), | 770 target.accept(this), |
768 js.string(node.methodName.name, "'"), | 771 js.string(node.methodName.name, "'"), |
769 args | 772 args |
770 ]); | 773 ]); |
771 } else { | 774 } else { |
772 return js.call( | 775 return js.call( |
773 'dart.dinvokef(#, #)', [node.methodName.accept(this), args]); | 776 'dart.dinvokef(#, #)', [node.methodName.accept(this), args]); |
774 } | 777 } |
775 } | 778 } |
776 | 779 |
777 // TODO(jmesserly): if this resolves to a getter returning a function with | 780 // TODO(jmesserly): if this resolves to a getter returning a function with |
778 // a call method, we don't generate the `.call` correctly. | 781 // a call method, we don't generate the `.call` correctly. |
779 | 782 |
780 var targetJs; | 783 var targetJs; |
781 if (target != null) { | 784 if (target != null) { |
782 targetJs = js.call('#.#', [target.accept(this), node.methodName.name]); | 785 targetJs = js.call('#.#', [target.accept(this), node.methodName.name]); |
783 } else { | 786 } else { |
784 targetJs = node.methodName.accept(this); | 787 targetJs = node.methodName.accept(this); |
785 } | 788 } |
786 | 789 |
787 return js.call('#(#)', [targetJs, node.argumentList.accept(this)]); | 790 return js.call('#(#)', [targetJs, node.argumentList.accept(this)]); |
788 } | 791 } |
789 | 792 |
| 793 /// Emits code for the `JS(...)` builtin. |
| 794 _emitForeignJS(MethodInvocation node) { |
| 795 var e = node.methodName.staticElement; |
| 796 if (e is FunctionElement && |
| 797 e.library.name == '_foreign_helper' && |
| 798 e.name == 'JS') { |
| 799 var args = node.argumentList.arguments; |
| 800 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer` |
| 801 var code = args[1] as StringLiteral; |
| 802 |
| 803 var template = js.parseForeignJS(code.stringValue); |
| 804 var result = template.instantiate(_visitList(args.skip(2))); |
| 805 // `throw` is emitted as a statement by `parseForeignJS`. |
| 806 assert(result is JS.Expression || node.parent is ExpressionStatement); |
| 807 return result; |
| 808 } |
| 809 return null; |
| 810 } |
| 811 |
790 @override | 812 @override |
791 JS.Expression visitFunctionExpressionInvocation( | 813 JS.Expression visitFunctionExpressionInvocation( |
792 FunctionExpressionInvocation node) { | 814 FunctionExpressionInvocation node) { |
793 var code; | 815 var code; |
794 if (rules.isDynamicCall(node.function)) { | 816 if (rules.isDynamicCall(node.function)) { |
795 code = 'dart.dinvokef(#, #)'; | 817 code = 'dart.dinvokef(#, #)'; |
796 } else { | 818 } else { |
797 code = '#(#)'; | 819 code = '#(#)'; |
798 } | 820 } |
799 return js.call( | 821 return js.call( |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 /// Choose a canonical name from the library element. | 1735 /// Choose a canonical name from the library element. |
1714 /// This never uses the library's name (the identifier in the `library` | 1736 /// This never uses the library's name (the identifier in the `library` |
1715 /// declaration) as it doesn't have any meaningful rules enforced. | 1737 /// declaration) as it doesn't have any meaningful rules enforced. |
1716 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 1738 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
1717 | 1739 |
1718 /// Path to file that will be generated for [info]. | 1740 /// Path to file that will be generated for [info]. |
1719 // TODO(jmesserly): library directory should be relative to its package | 1741 // TODO(jmesserly): library directory should be relative to its package |
1720 // root. For example, "package:dev_compiler/src/codegen/js_codegen.dart" would b
e: | 1742 // root. For example, "package:dev_compiler/src/codegen/js_codegen.dart" would b
e: |
1721 // "ddc/src/codegen/js_codegen.js" under the output directory. | 1743 // "ddc/src/codegen/js_codegen.js" under the output directory. |
1722 String jsOutputPath(LibraryInfo info) => '${info.name}/${info.name}.js'; | 1744 String jsOutputPath(LibraryInfo info) => '${info.name}/${info.name}.js'; |
OLD | NEW |