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 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 | 559 |
560 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { | 560 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { |
561 var name = type.name; | 561 var name = type.name; |
562 var genericName = '$name\$'; | 562 var genericName = '$name\$'; |
563 var typeParams = type.typeParameters.map((p) => p.name); | 563 var typeParams = type.typeParameters.map((p) => p.name); |
564 if (isPublic(name)) _exports.add(genericName); | 564 if (isPublic(name)) _exports.add(genericName); |
565 return js.statement('let # = dart.generic(function(#) { #; return #; });', | 565 return js.statement('let # = dart.generic(function(#) { #; return #; });', |
566 [genericName, typeParams, body, name]); | 566 [genericName, typeParams, body, name]); |
567 } | 567 } |
568 | 568 |
| 569 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 570 |
| 571 bool _deferIfNeeded(DartType type, ClassElement current) { |
| 572 if (type is ParameterizedType) { |
| 573 var typeArguments = type.typeArguments; |
| 574 for (var typeArg in typeArguments) { |
| 575 var typeElement = typeArg.element; |
| 576 // FIXME(vsm): This does not track mutual recursive dependences. |
| 577 if (current == typeElement || _deferIfNeeded(typeArg, current)) { |
| 578 return true; |
| 579 } |
| 580 } |
| 581 } |
| 582 return false; |
| 583 } |
| 584 |
569 JS.Expression _classHeritage(ClassElement element) { | 585 JS.Expression _classHeritage(ClassElement element) { |
570 var type = element.type; | 586 var type = element.type; |
571 if (type.isObject) return null; | 587 if (type.isObject) return null; |
572 | 588 |
573 // Assume we can load eagerly, until proven otherwise. | 589 // Assume we can load eagerly, until proven otherwise. |
574 _loader.startTopLevel(element); | 590 _loader.startTopLevel(element); |
575 | 591 |
576 JS.Expression heritage = _emitTypeName(type.superclass); | 592 // Find the super type |
| 593 JS.Expression heritage; |
| 594 var supertype = type.superclass; |
| 595 if (_deferIfNeeded(supertype, element)) { |
| 596 // Fall back to raw type. |
| 597 supertype = fillDynamicTypeArgs(supertype.element.type, rules.provider); |
| 598 _hasDeferredSupertype.add(element); |
| 599 } |
| 600 heritage = _emitTypeName(supertype); |
| 601 |
577 if (type.mixins.isNotEmpty) { | 602 if (type.mixins.isNotEmpty) { |
578 var mixins = type.mixins.map(_emitTypeName).toList(); | 603 var mixins = type.mixins.map(_emitTypeName).toList(); |
579 mixins.insert(0, heritage); | 604 mixins.insert(0, heritage); |
580 heritage = js.call('dart.mixin(#)', [mixins]); | 605 heritage = js.call('dart.mixin(#)', [mixins]); |
581 } | 606 } |
582 | 607 |
583 _loader.finishTopLevel(element); | 608 _loader.finishTopLevel(element); |
584 return heritage; | 609 return heritage; |
585 } | 610 } |
586 | 611 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 } | 719 } |
695 | 720 |
696 body.add(new JS.ClassDeclaration(cls)); | 721 body.add(new JS.ClassDeclaration(cls)); |
697 | 722 |
698 // TODO(jmesserly): we should really just extend native Array. | 723 // TODO(jmesserly): we should really just extend native Array. |
699 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 724 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { |
700 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', | 725 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', |
701 [classElem.name, _propertyName(jsPeerName)])); | 726 [classElem.name, _propertyName(jsPeerName)])); |
702 } | 727 } |
703 | 728 |
| 729 // Deferred Superclass |
| 730 if (_hasDeferredSupertype.contains(classElem)) { |
| 731 body.add(js.statement('#.prototype.__proto__ = #.prototype;', |
| 732 [name, _emitTypeName(classElem.type.superclass)])); |
| 733 } |
| 734 |
704 // Interfaces | 735 // Interfaces |
705 if (classElem.interfaces.isNotEmpty) { | 736 if (classElem.interfaces.isNotEmpty) { |
706 body.add(js.statement('#[dart.implements] = () => #;', [ | 737 body.add(js.statement('#[dart.implements] = () => #;', [ |
707 name, | 738 name, |
708 new JS.ArrayInitializer(new List<JS.Expression>.from( | 739 new JS.ArrayInitializer(new List<JS.Expression>.from( |
709 classElem.interfaces.map(_emitTypeName))) | 740 classElem.interfaces.map(_emitTypeName))) |
710 ])); | 741 ])); |
711 } | 742 } |
712 | 743 |
713 // Named constructors | 744 // Named constructors |
(...skipping 2602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3316 | 3347 |
3317 /// A special kind of element created by the compiler, signifying a temporary | 3348 /// A special kind of element created by the compiler, signifying a temporary |
3318 /// variable. These objects use instance equality, and should be shared | 3349 /// variable. These objects use instance equality, and should be shared |
3319 /// everywhere in the tree where they are treated as the same variable. | 3350 /// everywhere in the tree where they are treated as the same variable. |
3320 class TemporaryVariableElement extends LocalVariableElementImpl { | 3351 class TemporaryVariableElement extends LocalVariableElementImpl { |
3321 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3352 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3322 | 3353 |
3323 int get hashCode => identityHashCode(this); | 3354 int get hashCode => identityHashCode(this); |
3324 bool operator ==(Object other) => identical(this, other); | 3355 bool operator ==(Object other) => identical(this, other); |
3325 } | 3356 } |
OLD | NEW |