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; | 7 import 'dart:collection' show HashSet, HashMap; |
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 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 /// | 516 /// |
517 /// This will return `null` if the adapter was already added on a super type, | 517 /// This will return `null` if the adapter was already added on a super type, |
518 /// otherwise it returns the adapter code. | 518 /// otherwise it returns the adapter code. |
519 // TODO(jmesserly): should we adapt `Iterator` too? | 519 // TODO(jmesserly): should we adapt `Iterator` too? |
520 JS.Method _emitIterable(InterfaceType t) { | 520 JS.Method _emitIterable(InterfaceType t) { |
521 // If a parent had an `iterator` (concrete or abstract) or implements | 521 // If a parent had an `iterator` (concrete or abstract) or implements |
522 // Iterable, we know the adapter is already there, so we can skip it as a | 522 // Iterable, we know the adapter is already there, so we can skip it as a |
523 // simple code size optimization. | 523 // simple code size optimization. |
524 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); | 524 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); |
525 if (parent != null) return null; | 525 if (parent != null) return null; |
526 parent = findSupertype(t, _implementsIterable); | 526 var parentType = findSupertype(t, _implementsIterable); |
527 if (parent != null) return null; | 527 if (parentType != null) return null; |
528 | 528 |
529 // Otherwise, emit the adapter method, which wraps the Dart iterator in | 529 // Otherwise, emit the adapter method, which wraps the Dart iterator in |
530 // an ES6 iterator. | 530 // an ES6 iterator. |
531 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( | 531 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( |
532 'function() { return new dart.JsIterator(this.#); }', | 532 'function() { return new dart.JsIterator(this.#); }', |
533 [_emitMemberName('iterator', type: t)])); | 533 [_emitMemberName('iterator', type: t)])); |
534 } | 534 } |
535 | 535 |
536 /// Emit class members that need to come after the class declaration, such | 536 /// Emit class members that need to come after the class declaration, such |
537 /// as static fields. See [_emitClassMethods] for things that are emitted | 537 /// as static fields. See [_emitClassMethods] for things that are emitted |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 1132 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
1133 var accessor = node.staticElement; | 1133 var accessor = node.staticElement; |
1134 if (accessor == null) { | 1134 if (accessor == null) { |
1135 return js.commentExpression( | 1135 return js.commentExpression( |
1136 'Unimplemented unknown name', new JS.Identifier(node.name)); | 1136 'Unimplemented unknown name', new JS.Identifier(node.name)); |
1137 } | 1137 } |
1138 | 1138 |
1139 // Get the original declaring element. If we had a property accessor, this | 1139 // Get the original declaring element. If we had a property accessor, this |
1140 // indirects back to a (possibly synthetic) field. | 1140 // indirects back to a (possibly synthetic) field. |
1141 var element = accessor; | 1141 var element = accessor; |
1142 if (element is PropertyAccessorElement) element = accessor.variable; | 1142 if (accessor is PropertyAccessorElement) element = accessor.variable; |
1143 | 1143 |
1144 _loader.declareBeforeUse(element); | 1144 _loader.declareBeforeUse(element); |
1145 | 1145 |
1146 var name = element.name; | 1146 var name = element.name; |
1147 | 1147 |
1148 // type literal | 1148 // type literal |
1149 if (element is ClassElement || | 1149 if (element is ClassElement || |
1150 element is DynamicElementImpl || | 1150 element is DynamicElementImpl || |
1151 element is FunctionTypeAliasElement) { | 1151 element is FunctionTypeAliasElement) { |
1152 return _emitTypeName(fillDynamicTypeArgs(element.type, types)); | 1152 return _emitTypeName( |
| 1153 fillDynamicTypeArgs((element as dynamic).type, types)); |
1153 } | 1154 } |
1154 | 1155 |
1155 // library member | 1156 // library member |
1156 if (element.enclosingElement is CompilationUnitElement) { | 1157 if (element.enclosingElement is CompilationUnitElement) { |
1157 return _maybeQualifiedName( | 1158 return _maybeQualifiedName( |
1158 element, _emitMemberName(name, isStatic: true)); | 1159 element, _emitMemberName(name, isStatic: true)); |
1159 } | 1160 } |
1160 | 1161 |
1161 // Unqualified class member. This could mean implicit-this, or implicit | 1162 // Unqualified class member. This could mean implicit-this, or implicit |
1162 // call to a static from the same class. | 1163 // call to a static from the same class. |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1746 e.library.name == '_foreign_helper' && | 1747 e.library.name == '_foreign_helper' && |
1747 e.name == 'JS') { | 1748 e.name == 'JS') { |
1748 // Fix types for JS builtin calls. | 1749 // Fix types for JS builtin calls. |
1749 // | 1750 // |
1750 // This code was taken from analyzer. It's not super sophisticated: | 1751 // This code was taken from analyzer. It's not super sophisticated: |
1751 // only looks for the type name in dart:core, so we just copy it here. | 1752 // only looks for the type name in dart:core, so we just copy it here. |
1752 // | 1753 // |
1753 // TODO(jmesserly): we'll likely need something that can handle a wider | 1754 // TODO(jmesserly): we'll likely need something that can handle a wider |
1754 // variety of types, especially when we get to JS interop. | 1755 // variety of types, especially when we get to JS interop. |
1755 var args = expr.argumentList.arguments; | 1756 var args = expr.argumentList.arguments; |
1756 if (args.isNotEmpty && args.first is SimpleStringLiteral) { | 1757 var first = args.isNotEmpty ? args.first : null; |
1757 var types = args.first.stringValue; | 1758 if (first is SimpleStringLiteral) { |
| 1759 var types = first.stringValue; |
1758 if (!types.split('|').contains('Null')) { | 1760 if (!types.split('|').contains('Null')) { |
1759 return true; | 1761 return true; |
1760 } | 1762 } |
1761 } | 1763 } |
1762 } | 1764 } |
1763 } | 1765 } |
1764 return false; | 1766 return false; |
1765 } | 1767 } |
1766 | 1768 |
1767 JS.Expression notNull(Expression expr) { | 1769 JS.Expression notNull(Expression expr) { |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 !_isJSBuiltinType(type) && | 2054 !_isJSBuiltinType(type) && |
2053 _isNonNullableExpression(target)) { | 2055 _isNonNullableExpression(target)) { |
2054 return false; | 2056 return false; |
2055 } | 2057 } |
2056 return true; | 2058 return true; |
2057 } | 2059 } |
2058 | 2060 |
2059 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 2061 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
2060 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { | 2062 JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) { |
2061 var member = memberId.staticElement; | 2063 var member = memberId.staticElement; |
2062 if (member is PropertyAccessorElement) member = member.variable; | 2064 if (member is PropertyAccessorElement) { |
| 2065 member = (member as PropertyAccessorElement).variable; |
| 2066 } |
2063 bool isStatic = member is ClassMemberElement && member.isStatic; | 2067 bool isStatic = member is ClassMemberElement && member.isStatic; |
2064 if (isStatic) { | 2068 if (isStatic) { |
2065 _loader.declareBeforeUse(member); | 2069 _loader.declareBeforeUse(member); |
2066 } | 2070 } |
2067 var name = _emitMemberName(memberId.name, | 2071 var name = _emitMemberName(memberId.name, |
2068 type: getStaticType(target), isStatic: isStatic); | 2072 type: getStaticType(target), isStatic: isStatic); |
2069 if (rules.isDynamicTarget(target)) { | 2073 if (rules.isDynamicTarget(target)) { |
2070 return js.call('dart.$DLOAD(#, #)', [_visit(target), name]); | 2074 return js.call('dart.$DLOAD(#, #)', [_visit(target), name]); |
2071 } | 2075 } |
2072 | 2076 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2239 | 2243 |
2240 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which | 2244 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which |
2241 // has special case for typeof. | 2245 // has special case for typeof. |
2242 return new JS.If(js.call('dart.is(#, #)', [ | 2246 return new JS.If(js.call('dart.is(#, #)', [ |
2243 _visit(_catchParameter), | 2247 _visit(_catchParameter), |
2244 _emitTypeName(clause.exceptionType.type), | 2248 _emitTypeName(clause.exceptionType.type), |
2245 ]), then, otherwise); | 2249 ]), then, otherwise); |
2246 } | 2250 } |
2247 | 2251 |
2248 JS.Statement _statement(Iterable stmts) { | 2252 JS.Statement _statement(Iterable stmts) { |
2249 var s = stmts is List ? stmts : new List<JS.Statement>.from(stmts); | 2253 List s = stmts is List ? stmts : new List<JS.Statement>.from(stmts); |
2250 // TODO(jmesserly): empty block singleton? | 2254 // TODO(jmesserly): empty block singleton? |
2251 if (s.length == 0) return new JS.Block([]); | 2255 if (s.length == 0) return new JS.Block([]); |
2252 if (s.length == 1) return s[0]; | 2256 if (s.length == 1) return s[0]; |
2253 return new JS.Block(s); | 2257 return new JS.Block(s); |
2254 } | 2258 } |
2255 | 2259 |
2256 /// Visits the catch clause body. This skips the exception type guard, if any. | 2260 /// Visits the catch clause body. This skips the exception type guard, if any. |
2257 /// That is handled in [_visitCatch]. | 2261 /// That is handled in [_visitCatch]. |
2258 @override | 2262 @override |
2259 JS.Statement visitCatchClause(CatchClause node) { | 2263 JS.Statement visitCatchClause(CatchClause node) { |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2646 | 2650 |
2647 /// A special kind of element created by the compiler, signifying a temporary | 2651 /// A special kind of element created by the compiler, signifying a temporary |
2648 /// variable. These objects use instance equality, and should be shared | 2652 /// variable. These objects use instance equality, and should be shared |
2649 /// everywhere in the tree where they are treated as the same variable. | 2653 /// everywhere in the tree where they are treated as the same variable. |
2650 class TemporaryVariableElement extends LocalVariableElementImpl { | 2654 class TemporaryVariableElement extends LocalVariableElementImpl { |
2651 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2655 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
2652 | 2656 |
2653 int get hashCode => identityHashCode(this); | 2657 int get hashCode => identityHashCode(this); |
2654 bool operator ==(Object other) => identical(this, other); | 2658 bool operator ==(Object other) => identical(this, other); |
2655 } | 2659 } |
OLD | NEW |