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 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
6 | 6 |
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/src/generated/constant.dart'; | 9 import 'package:analyzer/src/generated/constant.dart'; |
10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 var supertype = element.supertype; | 372 var supertype = element.supertype; |
373 if (!supertype.isObject) { | 373 if (!supertype.isObject) { |
374 for (var ctor in element.constructors) { | 374 for (var ctor in element.constructors) { |
375 var parentCtor = supertype.lookUpConstructor(ctor.name, ctor.library); | 375 var parentCtor = supertype.lookUpConstructor(ctor.name, ctor.library); |
376 var fun = js.call('function() { super.#(...arguments); }', | 376 var fun = js.call('function() { super.#(...arguments); }', |
377 [_constructorName(parentCtor)]) as JS.Fun; | 377 [_constructorName(parentCtor)]) as JS.Fun; |
378 body.add(new JS.Method(_constructorName(ctor), fun)); | 378 body.add(new JS.Method(_constructorName(ctor), fun)); |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
382 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression( | 382 var classExpr = new JS.ClassExpression( |
383 new JS.Identifier(element.name), _classHeritage(element), body)); | 383 new JS.Identifier(element.name), _classHeritage(element), body); |
384 | 384 |
385 return _finishClassDef(element.type, classDecl); | 385 return _finishClassDef( |
| 386 element.type, _emitClassHeritageWorkaround(classExpr)); |
386 } | 387 } |
387 | 388 |
388 JS.Statement _emitJsType(String dartClassName, DartObject jsName) { | 389 JS.Statement _emitJsType(String dartClassName, DartObject jsName) { |
389 var jsTypeName = | 390 var jsTypeName = |
390 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 391 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
391 | 392 |
392 if (jsTypeName != null && jsTypeName != dartClassName) { | 393 if (jsTypeName != null && jsTypeName != dartClassName) { |
393 // We export the JS type as if it was a Dart type. For example this allows | 394 // We export the JS type as if it was a Dart type. For example this allows |
394 // `dom.InputElement` to actually be HTMLInputElement. | 395 // `dom.InputElement` to actually be HTMLInputElement. |
395 // TODO(jmesserly): if we had the JS name on the Element, we could just | 396 // TODO(jmesserly): if we had the JS name on the Element, we could just |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 JS.Expression _instantiateAnnotation(Annotation node) { | 668 JS.Expression _instantiateAnnotation(Annotation node) { |
668 var element = node.element; | 669 var element = node.element; |
669 if (element is ConstructorElement) { | 670 if (element is ConstructorElement) { |
670 return _emitInstanceCreationExpression(element, element.returnType, | 671 return _emitInstanceCreationExpression(element, element.returnType, |
671 node.constructorName, node.arguments, true); | 672 node.constructorName, node.arguments, true); |
672 } else { | 673 } else { |
673 return _visit(node.name); | 674 return _visit(node.name); |
674 } | 675 } |
675 } | 676 } |
676 | 677 |
| 678 _isQualifiedPath(JS.Expression node) => |
| 679 node is JS.Identifier || |
| 680 node is JS.PropertyAccess && |
| 681 _isQualifiedPath(node.receiver) && |
| 682 node.selector is JS.LiteralString; |
| 683 |
| 684 /// Workaround for Closure: super classes must be qualified paths. |
| 685 JS.Statement _emitClassHeritageWorkaround(JS.ClassExpression cls) { |
| 686 if (options.closure && |
| 687 cls.heritage != null && |
| 688 !_isQualifiedPath(cls.heritage)) { |
| 689 var superVar = new JS.TemporaryId(cls.name.name + r'$super'); |
| 690 return _statement([ |
| 691 js.statement('const # = #;', [superVar, cls.heritage]), |
| 692 new JS.ClassDeclaration( |
| 693 new JS.ClassExpression(cls.name, superVar, cls.methods)) |
| 694 ]); |
| 695 } |
| 696 return new JS.ClassDeclaration(cls); |
| 697 } |
| 698 |
677 /// Emit class members that need to come after the class declaration, such | 699 /// Emit class members that need to come after the class declaration, such |
678 /// as static fields. See [_emitClassMethods] for things that are emitted | 700 /// as static fields. See [_emitClassMethods] for things that are emitted |
679 /// inside the ES6 `class { ... }` node. | 701 /// inside the ES6 `class { ... }` node. |
680 JS.Statement _finishClassMembers( | 702 JS.Statement _finishClassMembers( |
681 ClassElement classElem, | 703 ClassElement classElem, |
682 JS.ClassExpression cls, | 704 JS.ClassExpression cls, |
683 List<ConstructorDeclaration> ctors, | 705 List<ConstructorDeclaration> ctors, |
684 List<FieldDeclaration> fields, | 706 List<FieldDeclaration> fields, |
685 List<FieldDeclaration> staticFields, | 707 List<FieldDeclaration> staticFields, |
686 List<MethodDeclaration> methods, | 708 List<MethodDeclaration> methods, |
687 List<Annotation> metadata, | 709 List<Annotation> metadata, |
688 String jsPeerName) { | 710 String jsPeerName) { |
689 var name = classElem.name; | 711 var name = classElem.name; |
690 var body = <JS.Statement>[]; | 712 var body = <JS.Statement>[]; |
691 | 713 |
692 if (_extensionTypes.contains(classElem)) { | 714 if (_extensionTypes.contains(classElem)) { |
693 var dartxNames = <JS.Expression>[]; | 715 var dartxNames = <JS.Expression>[]; |
694 for (var m in methods) { | 716 for (var m in methods) { |
695 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 717 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { |
696 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); | 718 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); |
697 } | 719 } |
698 } | 720 } |
699 if (dartxNames.isNotEmpty) { | 721 if (dartxNames.isNotEmpty) { |
700 body.add(js.statement('dart.defineExtensionNames(#)', | 722 body.add(js.statement('dart.defineExtensionNames(#)', |
701 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | 723 [new JS.ArrayInitializer(dartxNames, multiline: true)])); |
702 } | 724 } |
703 } | 725 } |
704 | 726 |
705 body.add(new JS.ClassDeclaration(cls)); | 727 body.add(_emitClassHeritageWorkaround(cls)); |
706 | 728 |
707 // TODO(jmesserly): we should really just extend native Array. | 729 // TODO(jmesserly): we should really just extend native Array. |
708 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 730 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { |
709 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', | 731 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', |
710 [classElem.name, _propertyName(jsPeerName)])); | 732 [classElem.name, _propertyName(jsPeerName)])); |
711 } | 733 } |
712 | 734 |
713 // Deferred Superclass | 735 // Deferred Superclass |
714 if (_hasDeferredSupertype.contains(classElem)) { | 736 if (_hasDeferredSupertype.contains(classElem)) { |
715 body.add(js.statement('#.prototype.__proto__ = #.prototype;', | 737 body.add(js.statement('#.prototype.__proto__ = #.prototype;', |
(...skipping 2873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3589 | 3611 |
3590 /// A special kind of element created by the compiler, signifying a temporary | 3612 /// A special kind of element created by the compiler, signifying a temporary |
3591 /// variable. These objects use instance equality, and should be shared | 3613 /// variable. These objects use instance equality, and should be shared |
3592 /// everywhere in the tree where they are treated as the same variable. | 3614 /// everywhere in the tree where they are treated as the same variable. |
3593 class TemporaryVariableElement extends LocalVariableElementImpl { | 3615 class TemporaryVariableElement extends LocalVariableElementImpl { |
3594 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3616 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3595 | 3617 |
3596 int get hashCode => identityHashCode(this); | 3618 int get hashCode => identityHashCode(this); |
3597 bool operator ==(Object other) => identical(this, other); | 3619 bool operator ==(Object other) => identical(this, other); |
3598 } | 3620 } |
OLD | NEW |