| 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 dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
| 6 | 6 |
| 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
| 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 84 |
| 85 /// The name for the library's exports inside itself. | 85 /// The name for the library's exports inside itself. |
| 86 /// `exports` was chosen as the most similar to ES module patterns. | 86 /// `exports` was chosen as the most similar to ES module patterns. |
| 87 final _exportsVar = new JS.TemporaryId('exports'); | 87 final _exportsVar = new JS.TemporaryId('exports'); |
| 88 final _namedArgTemp = new JS.TemporaryId('opts'); | 88 final _namedArgTemp = new JS.TemporaryId('opts'); |
| 89 | 89 |
| 90 ConstFieldVisitor _constField; | 90 ConstFieldVisitor _constField; |
| 91 | 91 |
| 92 ModuleItemLoadOrder _loader; | 92 ModuleItemLoadOrder _loader; |
| 93 | 93 |
| 94 /// _interceptors.JSArray<E>, used for List literals. |
| 95 ClassElement _jsArray; |
| 96 |
| 94 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, | 97 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, |
| 95 this._extensionTypes, this._fieldsNeedingStorage) | 98 this._extensionTypes, this._fieldsNeedingStorage) |
| 96 : compiler = compiler, | 99 : compiler = compiler, |
| 97 options = compiler.options, | 100 options = compiler.options, |
| 98 rules = compiler.rules, | 101 rules = compiler.rules, |
| 99 root = compiler.entryPointUri { | 102 root = compiler.entryPointUri { |
| 100 _loader = new ModuleItemLoadOrder(_emitModuleItem); | 103 _loader = new ModuleItemLoadOrder(_emitModuleItem); |
| 104 |
| 105 var context = compiler.context; |
| 106 var src = context.sourceFactory.forUri('dart:_interceptors'); |
| 107 var interceptors = context.computeLibraryElement(src); |
| 108 _jsArray = interceptors.getType('JSArray'); |
| 101 } | 109 } |
| 102 | 110 |
| 103 LibraryElement get currentLibrary => libraryInfo.library; | 111 LibraryElement get currentLibrary => libraryInfo.library; |
| 104 TypeProvider get types => rules.provider; | 112 TypeProvider get types => rules.provider; |
| 105 | 113 |
| 106 JS.Program emitLibrary(LibraryUnit library) { | 114 JS.Program emitLibrary(LibraryUnit library) { |
| 107 String jsDefaultValue = null; | 115 String jsDefaultValue = null; |
| 108 | 116 |
| 109 // Modify the AST to make coercions explicit. | 117 // Modify the AST to make coercions explicit. |
| 110 new CoercionReifier(library, compiler).reify(); | 118 new CoercionReifier(library, compiler).reify(); |
| (...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 code = '#.#(#)'; | 1545 code = '#.#(#)'; |
| 1538 } | 1546 } |
| 1539 | 1547 |
| 1540 return js.call( | 1548 return js.call( |
| 1541 code, [_visit(target), memberName, _visit(node.argumentList)]); | 1549 code, [_visit(target), memberName, _visit(node.argumentList)]); |
| 1542 } | 1550 } |
| 1543 | 1551 |
| 1544 /// Emits code for the `JS(...)` builtin. | 1552 /// Emits code for the `JS(...)` builtin. |
| 1545 _emitForeignJS(MethodInvocation node) { | 1553 _emitForeignJS(MethodInvocation node) { |
| 1546 var e = node.methodName.staticElement; | 1554 var e = node.methodName.staticElement; |
| 1547 if (e is FunctionElement && | 1555 if (isInlineJS(e)) { |
| 1548 e.library.name == '_foreign_helper' && | |
| 1549 e.name == 'JS') { | |
| 1550 var args = node.argumentList.arguments; | 1556 var args = node.argumentList.arguments; |
| 1551 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer` | 1557 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer` |
| 1552 var code = args[1] as StringLiteral; | 1558 var code = args[1] as StringLiteral; |
| 1553 | 1559 |
| 1554 var template = js.parseForeignJS(code.stringValue); | 1560 var template = js.parseForeignJS(code.stringValue); |
| 1555 var result = template.instantiate(_visitList(args.skip(2))); | 1561 var result = template.instantiate(_visitList(args.skip(2))); |
| 1556 // `throw` is emitted as a statement by `parseForeignJS`. | 1562 // `throw` is emitted as a statement by `parseForeignJS`. |
| 1557 assert(result is JS.Expression || node.parent is ExpressionStatement); | 1563 assert(result is JS.Expression || node.parent is ExpressionStatement); |
| 1558 return result; | 1564 return result; |
| 1559 } | 1565 } |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 } else if (expr is PostfixExpression) { | 1874 } else if (expr is PostfixExpression) { |
| 1869 type = getStaticType(expr.operand); | 1875 type = getStaticType(expr.operand); |
| 1870 } | 1876 } |
| 1871 if (type != null && _isJSBuiltinType(type)) { | 1877 if (type != null && _isJSBuiltinType(type)) { |
| 1872 return true; | 1878 return true; |
| 1873 } | 1879 } |
| 1874 if (expr is MethodInvocation) { | 1880 if (expr is MethodInvocation) { |
| 1875 // TODO(vsm): This logic overlaps with the resolver. | 1881 // TODO(vsm): This logic overlaps with the resolver. |
| 1876 // Where is the best place to put this? | 1882 // Where is the best place to put this? |
| 1877 var e = expr.methodName.staticElement; | 1883 var e = expr.methodName.staticElement; |
| 1878 if (e is FunctionElement && | 1884 if (isInlineJS(e)) { |
| 1879 e.library.name == '_foreign_helper' && | |
| 1880 e.name == 'JS') { | |
| 1881 // Fix types for JS builtin calls. | 1885 // Fix types for JS builtin calls. |
| 1882 // | 1886 // |
| 1883 // This code was taken from analyzer. It's not super sophisticated: | 1887 // This code was taken from analyzer. It's not super sophisticated: |
| 1884 // only looks for the type name in dart:core, so we just copy it here. | 1888 // only looks for the type name in dart:core, so we just copy it here. |
| 1885 // | 1889 // |
| 1886 // TODO(jmesserly): we'll likely need something that can handle a wider | 1890 // TODO(jmesserly): we'll likely need something that can handle a wider |
| 1887 // variety of types, especially when we get to JS interop. | 1891 // variety of types, especially when we get to JS interop. |
| 1888 var args = expr.argumentList.arguments; | 1892 var args = expr.argumentList.arguments; |
| 1889 var first = args.isNotEmpty ? args.first : null; | 1893 var first = args.isNotEmpty ? args.first : null; |
| 1890 if (first is SimpleStringLiteral) { | 1894 if (first is SimpleStringLiteral) { |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2474 return _emitConst(emitSymbol); | 2478 return _emitConst(emitSymbol); |
| 2475 } | 2479 } |
| 2476 | 2480 |
| 2477 @override | 2481 @override |
| 2478 visitListLiteral(ListLiteral node) { | 2482 visitListLiteral(ListLiteral node) { |
| 2479 emitList() { | 2483 emitList() { |
| 2480 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); | 2484 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); |
| 2481 ParameterizedType type = node.staticType; | 2485 ParameterizedType type = node.staticType; |
| 2482 var elementType = type.typeArguments.single; | 2486 var elementType = type.typeArguments.single; |
| 2483 if (elementType != types.dynamicType) { | 2487 if (elementType != types.dynamicType) { |
| 2488 // dart.list helper internally depends on _interceptors.JSArray. |
| 2489 _loader.declareBeforeUse(_jsArray); |
| 2484 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); | 2490 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); |
| 2485 } | 2491 } |
| 2486 return list; | 2492 return list; |
| 2487 } | 2493 } |
| 2488 if (node.constKeyword != null) return _emitConst(emitList); | 2494 if (node.constKeyword != null) return _emitConst(emitList); |
| 2489 return emitList(); | 2495 return emitList(); |
| 2490 } | 2496 } |
| 2491 | 2497 |
| 2492 @override | 2498 @override |
| 2493 visitMapLiteral(MapLiteral node) { | 2499 visitMapLiteral(MapLiteral node) { |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 | 2779 |
| 2774 /// A special kind of element created by the compiler, signifying a temporary | 2780 /// A special kind of element created by the compiler, signifying a temporary |
| 2775 /// variable. These objects use instance equality, and should be shared | 2781 /// variable. These objects use instance equality, and should be shared |
| 2776 /// everywhere in the tree where they are treated as the same variable. | 2782 /// everywhere in the tree where they are treated as the same variable. |
| 2777 class TemporaryVariableElement extends LocalVariableElementImpl { | 2783 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2778 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2784 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2779 | 2785 |
| 2780 int get hashCode => identityHashCode(this); | 2786 int get hashCode => identityHashCode(this); |
| 2781 bool operator ==(Object other) => identical(this, other); | 2787 bool operator ==(Object other) => identical(this, other); |
| 2782 } | 2788 } |
| OLD | NEW |