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 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 } | 498 } |
499 | 499 |
500 /// Given a class element and body, complete the class declaration. | 500 /// Given a class element and body, complete the class declaration. |
501 /// This handles generic type parameters, laziness (in library-cycle cases), | 501 /// This handles generic type parameters, laziness (in library-cycle cases), |
502 /// and ensuring dependencies are loaded first. | 502 /// and ensuring dependencies are loaded first. |
503 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { | 503 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { |
504 var name = type.name; | 504 var name = type.name; |
505 var genericName = '$name\$'; | 505 var genericName = '$name\$'; |
506 | 506 |
507 JS.Statement genericDef = null; | 507 JS.Statement genericDef = null; |
508 if (_boundTypeParametersOf(type).isNotEmpty) { | 508 if (_typeFormalsOf(type).isNotEmpty) { |
509 genericDef = _emitGenericClassDef(type, body); | 509 genericDef = _emitGenericClassDef(type, body); |
510 } | 510 } |
511 // The base class and all mixins must be declared before this class. | 511 // The base class and all mixins must be declared before this class. |
512 if (!_loader.isLoaded(type.element)) { | 512 if (!_loader.isLoaded(type.element)) { |
513 // TODO(jmesserly): the lazy class def is a simple solution for now. | 513 // TODO(jmesserly): the lazy class def is a simple solution for now. |
514 // We may want to consider other options in the future. | 514 // We may want to consider other options in the future. |
515 | 515 |
516 if (genericDef != null) { | 516 if (genericDef != null) { |
517 return js.statement( | 517 return js.statement( |
518 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', | 518 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', |
(...skipping 11 matching lines...) Expand all Loading... |
530 var dynType = fillDynamicTypeArgs(type, types); | 530 var dynType = fillDynamicTypeArgs(type, types); |
531 var genericInst = _emitTypeName(dynType, lowerGeneric: true); | 531 var genericInst = _emitTypeName(dynType, lowerGeneric: true); |
532 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); | 532 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); |
533 } | 533 } |
534 return body; | 534 return body; |
535 } | 535 } |
536 | 536 |
537 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { | 537 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { |
538 var name = type.name; | 538 var name = type.name; |
539 var genericName = '$name\$'; | 539 var genericName = '$name\$'; |
540 var typeParams = _boundTypeParametersOf(type).map((p) => p.name); | 540 var typeParams = _typeFormalsOf(type).map((p) => p.name); |
541 if (isPublic(name)) _exports.add(genericName); | 541 if (isPublic(name)) _exports.add(genericName); |
542 return js.statement('const # = dart.generic(function(#) { #; return #; });', | 542 return js.statement('const # = dart.generic(function(#) { #; return #; });', |
543 [genericName, typeParams, body, name]); | 543 [genericName, typeParams, body, name]); |
544 } | 544 } |
545 | 545 |
546 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 546 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
547 | 547 |
548 bool _deferIfNeeded(DartType type, ClassElement current) { | 548 bool _deferIfNeeded(DartType type, ClassElement current) { |
549 if (type is ParameterizedType) { | 549 if (type is ParameterizedType) { |
550 var typeArguments = type.typeArguments; | 550 var typeArguments = type.typeArguments; |
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 var accessor = node.staticElement; | 1549 var accessor = node.staticElement; |
1550 if (accessor == null) { | 1550 if (accessor == null) { |
1551 return js.commentExpression( | 1551 return js.commentExpression( |
1552 'Unimplemented unknown name', new JS.Identifier(node.name)); | 1552 'Unimplemented unknown name', new JS.Identifier(node.name)); |
1553 } | 1553 } |
1554 | 1554 |
1555 // Get the original declaring element. If we had a property accessor, this | 1555 // Get the original declaring element. If we had a property accessor, this |
1556 // indirects back to a (possibly synthetic) field. | 1556 // indirects back to a (possibly synthetic) field. |
1557 var element = accessor; | 1557 var element = accessor; |
1558 if (accessor is PropertyAccessorElement) element = accessor.variable; | 1558 if (accessor is PropertyAccessorElement) element = accessor.variable; |
1559 if (accessor is FunctionMember) element = accessor.baseElement; | |
1560 | 1559 |
1561 _loader.declareBeforeUse(element); | 1560 _loader.declareBeforeUse(element); |
1562 | 1561 |
1563 // type literal | 1562 // type literal |
1564 if (element is ClassElement || | 1563 if (element is ClassElement || |
1565 element is DynamicElementImpl || | 1564 element is DynamicElementImpl || |
1566 element is FunctionTypeAliasElement) { | 1565 element is FunctionTypeAliasElement) { |
1567 return _emitTypeName( | 1566 return _emitTypeName( |
1568 fillDynamicTypeArgs((element as dynamic).type, types)); | 1567 fillDynamicTypeArgs((element as dynamic).type, types)); |
1569 } | 1568 } |
(...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3255 } | 3254 } |
3256 | 3255 |
3257 /// Visits a list of expressions, creating a comma expression if needed in JS. | 3256 /// Visits a list of expressions, creating a comma expression if needed in JS. |
3258 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { | 3257 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { |
3259 if (nodes == null || nodes.isEmpty) return null; | 3258 if (nodes == null || nodes.isEmpty) return null; |
3260 return new JS.Expression.binary( | 3259 return new JS.Expression.binary( |
3261 _visitList(nodes) as List<JS.Expression>, operator); | 3260 _visitList(nodes) as List<JS.Expression>, operator); |
3262 } | 3261 } |
3263 | 3262 |
3264 /// Return the bound type parameters for a ParameterizedType | 3263 /// Return the bound type parameters for a ParameterizedType |
3265 List<TypeParameterElement> _boundTypeParametersOf(ParameterizedType type) { | 3264 List<TypeParameterElement> _typeFormalsOf(ParameterizedType type) { |
3266 return (type is FunctionType) | 3265 return type is FunctionType ? type.typeFormals : type.typeParameters; |
3267 ? type.boundTypeParameters | |
3268 : type.typeParameters; | |
3269 } | 3266 } |
3270 | 3267 |
3271 /// Like [_emitMemberName], but for declaration sites. | 3268 /// Like [_emitMemberName], but for declaration sites. |
3272 /// | 3269 /// |
3273 /// Unlike call sites, we always have an element available, so we can use it | 3270 /// Unlike call sites, we always have an element available, so we can use it |
3274 /// directly rather than computing the relevant options for [_emitMemberName]. | 3271 /// directly rather than computing the relevant options for [_emitMemberName]. |
3275 JS.Expression _elementMemberName(ExecutableElement e, | 3272 JS.Expression _elementMemberName(ExecutableElement e, |
3276 {bool allowExtensions: true}) { | 3273 {bool allowExtensions: true}) { |
3277 String name; | 3274 String name; |
3278 if (e is PropertyAccessorElement) { | 3275 if (e is PropertyAccessorElement) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3552 | 3549 |
3553 /// A special kind of element created by the compiler, signifying a temporary | 3550 /// A special kind of element created by the compiler, signifying a temporary |
3554 /// variable. These objects use instance equality, and should be shared | 3551 /// variable. These objects use instance equality, and should be shared |
3555 /// everywhere in the tree where they are treated as the same variable. | 3552 /// everywhere in the tree where they are treated as the same variable. |
3556 class TemporaryVariableElement extends LocalVariableElementImpl { | 3553 class TemporaryVariableElement extends LocalVariableElementImpl { |
3557 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3554 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3558 | 3555 |
3559 int get hashCode => identityHashCode(this); | 3556 int get hashCode => identityHashCode(this); |
3560 bool operator ==(Object other) => identical(this, other); | 3557 bool operator ==(Object other) => identical(this, other); |
3561 } | 3558 } |
OLD | NEW |