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 | 2 |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 | 747 |
748 var body = <JS.Statement>[]; | 748 var body = <JS.Statement>[]; |
749 var extensions = _extensionsToImplement(classElem); | 749 var extensions = _extensionsToImplement(classElem); |
750 _initExtensionSymbols(classElem, methods, fields, body); | 750 _initExtensionSymbols(classElem, methods, fields, body); |
751 _emitSuperHelperSymbols(_superHelperSymbols, body); | 751 _emitSuperHelperSymbols(_superHelperSymbols, body); |
752 | 752 |
753 // Emit the class, e.g. `core.Object = class Object { ... }` | 753 // Emit the class, e.g. `core.Object = class Object { ... }` |
754 _defineClass(classElem, className, classExpr, isCallable, body); | 754 _defineClass(classElem, className, classExpr, isCallable, body); |
755 | 755 |
756 // Emit things that come after the ES6 `class ... { ... }`. | 756 // Emit things that come after the ES6 `class ... { ... }`. |
757 var jsPeerName = _getJSPeerName(classElem); | 757 var jsPeerNames = _getJSPeerNames(classElem); |
758 _setBaseClass(classElem, className, jsPeerName, body); | 758 _setBaseClass(classElem, className, jsPeerNames, body); |
759 | 759 |
760 _emitClassTypeTests(classElem, className, body); | 760 _emitClassTypeTests(classElem, className, body); |
761 | 761 |
762 _defineNamedConstructors(ctors, body, className, isCallable); | 762 _defineNamedConstructors(ctors, body, className, isCallable); |
763 _emitVirtualFieldSymbols(virtualFieldSymbols, body); | 763 _emitVirtualFieldSymbols(virtualFieldSymbols, body); |
764 _emitClassSignature( | 764 _emitClassSignature( |
765 methods, allFields, classElem, ctors, extensions, className, body); | 765 methods, allFields, classElem, ctors, extensions, className, body); |
766 _defineExtensionMembers(extensions, className, body); | 766 _defineExtensionMembers(extensions, className, body); |
767 _emitClassMetadata(node.metadata, className, body); | 767 _emitClassMetadata(node.metadata, className, body); |
768 | 768 |
769 JS.Statement classDef = _statement(body); | 769 JS.Statement classDef = _statement(body); |
770 var typeFormals = classElem.typeParameters; | 770 var typeFormals = classElem.typeParameters; |
771 if (typeFormals.isNotEmpty) { | 771 if (typeFormals.isNotEmpty) { |
772 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); | 772 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); |
773 } | 773 } |
774 | 774 |
775 body = <JS.Statement>[classDef]; | 775 body = <JS.Statement>[classDef]; |
776 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); | 776 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); |
777 _registerExtensionType(classElem, jsPeerName, body); | 777 for (var peer in jsPeerNames) { |
| 778 _registerExtensionType(classElem, peer, body); |
| 779 } |
778 return _statement(body); | 780 return _statement(body); |
779 } | 781 } |
780 | 782 |
781 /// Emits code to support a class with a "call" method and an unnamed | 783 /// Emits code to support a class with a "call" method and an unnamed |
782 /// constructor. | 784 /// constructor. |
783 /// | 785 /// |
784 /// This ensures instances created by the unnamed constructor are functions. | 786 /// This ensures instances created by the unnamed constructor are functions. |
785 /// Named constructors are handled elsewhere, see [_defineNamedConstructors]. | 787 /// Named constructors are handled elsewhere, see [_defineNamedConstructors]. |
786 JS.Expression _emitCallableClass( | 788 JS.Expression _emitCallableClass( |
787 JS.ClassExpression classExpr, ConstructorElement unnamedCtor) { | 789 JS.ClassExpression classExpr, ConstructorElement unnamedCtor) { |
(...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 node.constructorName, node.arguments, true); | 1564 node.constructorName, node.arguments, true); |
1563 } else { | 1565 } else { |
1564 return _visit(node.name); | 1566 return _visit(node.name); |
1565 } | 1567 } |
1566 } | 1568 } |
1567 | 1569 |
1568 /// Gets the JS peer for this Dart type if any, otherwise null. | 1570 /// Gets the JS peer for this Dart type if any, otherwise null. |
1569 /// | 1571 /// |
1570 /// For example for dart:_interceptors `JSArray` this will return "Array", | 1572 /// For example for dart:_interceptors `JSArray` this will return "Array", |
1571 /// referring to the JavaScript built-in `Array` type. | 1573 /// referring to the JavaScript built-in `Array` type. |
1572 String _getJSPeerName(ClassElement classElem) { | 1574 List<String> _getJSPeerNames(ClassElement classElem) { |
1573 var jsPeerName = getAnnotationName( | 1575 var jsPeerNames = getAnnotationName( |
1574 classElem, | 1576 classElem, |
1575 (a) => | 1577 (a) => |
1576 isJsPeerInterface(a) || | 1578 isJsPeerInterface(a) || |
1577 isNativeAnnotation(a) && _extensionTypes.isNativeClass(classElem)); | 1579 isNativeAnnotation(a) && _extensionTypes.isNativeClass(classElem)); |
1578 if (jsPeerName != null && jsPeerName.contains(',')) { | 1580 if (jsPeerNames != null) { |
1579 jsPeerName = jsPeerName.split(',')[0]; | 1581 // Omit the special name "!nonleaf" and any future hacks starting with "!" |
| 1582 return jsPeerNames |
| 1583 .split(',') |
| 1584 .where((peer) => !peer.startsWith("!")) |
| 1585 .toList(); |
| 1586 } else { |
| 1587 return []; |
1580 } | 1588 } |
1581 return jsPeerName; | |
1582 } | 1589 } |
1583 | 1590 |
1584 void _registerExtensionType( | 1591 void _registerExtensionType( |
1585 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { | 1592 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { |
1586 if (jsPeerName != null) { | 1593 if (jsPeerName != null) { |
1587 body.add(js.statement('dart.registerExtension(dart.global.#, #);', | 1594 body.add(js.statement('dart.registerExtension(dart.global.#, #);', |
1588 [_propertyName(jsPeerName), _emitTopLevelName(classElem)])); | 1595 [_propertyName(jsPeerName), _emitTopLevelName(classElem)])); |
1589 } | 1596 } |
1590 } | 1597 } |
1591 | 1598 |
1592 void _setBaseClass(ClassElement classElem, JS.Expression className, | 1599 void _setBaseClass(ClassElement classElem, JS.Expression className, |
1593 String jsPeerName, List<JS.Statement> body) { | 1600 List<String> jsPeerNames, List<JS.Statement> body) { |
1594 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 1601 if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) { |
1595 // TODO(jmesserly): we should really just extend Array in the first place. | 1602 for (var peer in jsPeerNames) { |
1596 var newBaseClass = js.call('dart.global.#', [jsPeerName]); | 1603 // TODO(jmesserly): we should just extend Array in the first place |
1597 body.add(js.statement( | 1604 var newBaseClass = js.call('dart.global.#', [peer]); |
1598 'dart.setExtensionBaseClass(#, #);', [className, newBaseClass])); | 1605 body.add(js.statement( |
| 1606 'dart.setExtensionBaseClass(#, #);', [className, newBaseClass])); |
| 1607 } |
1599 } else if (_hasDeferredSupertype.contains(classElem)) { | 1608 } else if (_hasDeferredSupertype.contains(classElem)) { |
1600 var newBaseClass = _emitType(classElem.type.superclass, | 1609 var newBaseClass = _emitType(classElem.type.superclass, |
1601 nameType: false, subClass: classElem, className: className); | 1610 nameType: false, subClass: classElem, className: className); |
1602 body.add( | 1611 body.add( |
1603 js.statement('dart.setBaseClass(#, #);', [className, newBaseClass])); | 1612 js.statement('dart.setBaseClass(#, #);', [className, newBaseClass])); |
1604 } | 1613 } |
1605 } | 1614 } |
1606 | 1615 |
1607 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, | 1616 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, |
1608 List<JS.Statement> body, JS.Expression className, bool isCallable) { | 1617 List<JS.Statement> body, JS.Expression className, bool isCallable) { |
(...skipping 3888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5497 } | 5506 } |
5498 | 5507 |
5499 bool isLibraryPrefix(Expression node) => | 5508 bool isLibraryPrefix(Expression node) => |
5500 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5509 node is SimpleIdentifier && node.staticElement is PrefixElement; |
5501 | 5510 |
5502 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5511 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
5503 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5512 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
5504 | 5513 |
5505 bool _isDartRuntime(LibraryElement l) => | 5514 bool _isDartRuntime(LibraryElement l) => |
5506 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5515 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |