| 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 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 if (isGeneric) { | 820 if (isGeneric) { |
| 821 if (isMixinAlias) { | 821 if (isMixinAlias) { |
| 822 block.add(js.statement('const # = #;', [className, classExpr])); | 822 block.add(js.statement('const # = #;', [className, classExpr])); |
| 823 } else { | 823 } else { |
| 824 block.add(new JS.ClassDeclaration(classExpr)); | 824 block.add(new JS.ClassDeclaration(classExpr)); |
| 825 } | 825 } |
| 826 } else { | 826 } else { |
| 827 block.add(js.statement('# = #;', [className, classExpr])); | 827 block.add(js.statement('# = #;', [className, classExpr])); |
| 828 } | 828 } |
| 829 | 829 |
| 830 if (!isMixinAlias) _defineConstructors(classElem, className, [], block, []); | 830 if (!isMixinAlias) { |
| 831 block.addAll(_defineConstructors(classElem, className, [], [])); |
| 832 } |
| 831 | 833 |
| 832 if (classElem.interfaces.isNotEmpty) { | 834 if (classElem.interfaces.isNotEmpty) { |
| 833 block.add(js.statement('#[#.implements] = () => #;', [ | 835 block.add(js.statement('#[#.implements] = () => #;', [ |
| 834 className, | 836 className, |
| 835 _runtimeModule, | 837 _runtimeModule, |
| 836 new JS.ArrayInitializer(classElem.interfaces.map(_emitType).toList()) | 838 new JS.ArrayInitializer(classElem.interfaces.map(_emitType).toList()) |
| 837 ])); | 839 ])); |
| 838 } | 840 } |
| 839 | 841 |
| 840 if (isGeneric) { | 842 if (isGeneric) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 // type parameter. So we can use their local variable name directly. | 891 // type parameter. So we can use their local variable name directly. |
| 890 className = new JS.Identifier(classElem.name); | 892 className = new JS.Identifier(classElem.name); |
| 891 } else { | 893 } else { |
| 892 className = _emitTopLevelName(classElem); | 894 className = _emitTopLevelName(classElem); |
| 893 } | 895 } |
| 894 | 896 |
| 895 var savedClassProperties = _classProperties; | 897 var savedClassProperties = _classProperties; |
| 896 _classProperties = | 898 _classProperties = |
| 897 new ClassPropertyModel.build(_extensionTypes, virtualFields, classElem); | 899 new ClassPropertyModel.build(_extensionTypes, virtualFields, classElem); |
| 898 | 900 |
| 901 var jsCtors = _defineConstructors(classElem, className, fields, ctors); |
| 899 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node), | 902 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node), |
| 900 fields: allFields); | 903 fields: allFields); |
| 901 | 904 |
| 902 var body = <JS.Statement>[]; | 905 var body = <JS.Statement>[]; |
| 903 _initExtensionSymbols(classElem, methods, fields, body); | 906 _initExtensionSymbols(classElem, methods, fields, body); |
| 904 _emitSuperHelperSymbols(_superHelperSymbols, body); | 907 _emitSuperHelperSymbols(_superHelperSymbols, body); |
| 905 | 908 |
| 906 // Emit the class, e.g. `core.Object = class Object { ... }` | 909 // Emit the class, e.g. `core.Object = class Object { ... }` |
| 907 _defineClass(classElem, className, classExpr, body); | 910 _defineClass(classElem, className, classExpr, body); |
| 908 _defineConstructors(classElem, className, fields, body, ctors); | 911 body.addAll(jsCtors); |
| 909 | 912 |
| 910 // Emit things that come after the ES6 `class ... { ... }`. | 913 // Emit things that come after the ES6 `class ... { ... }`. |
| 911 var jsPeerNames = _getJSPeerNames(classElem); | 914 var jsPeerNames = _getJSPeerNames(classElem); |
| 912 JS.Statement deferredBaseClass = | 915 JS.Statement deferredBaseClass = |
| 913 _setBaseClass(classElem, className, jsPeerNames, body); | 916 _setBaseClass(classElem, className, jsPeerNames, body); |
| 914 | 917 |
| 915 _emitClassTypeTests(classElem, className, body); | 918 _emitClassTypeTests(classElem, className, body); |
| 916 | 919 |
| 917 _emitVirtualFieldSymbols(classElem, body); | 920 _emitVirtualFieldSymbols(classElem, body); |
| 918 _emitClassSignature(methods, allFields, classElem, ctors, className, body); | 921 _emitClassSignature(methods, allFields, classElem, ctors, className, body); |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 } | 1711 } |
| 1709 var deferredBaseClass = _callHelperStatement( | 1712 var deferredBaseClass = _callHelperStatement( |
| 1710 'setBaseClass(#, #);', [className, newBaseClass]); | 1713 'setBaseClass(#, #);', [className, newBaseClass]); |
| 1711 if (typeFormals.isNotEmpty) return deferredBaseClass; | 1714 if (typeFormals.isNotEmpty) return deferredBaseClass; |
| 1712 body.add(deferredBaseClass); | 1715 body.add(deferredBaseClass); |
| 1713 } | 1716 } |
| 1714 return null; | 1717 return null; |
| 1715 } | 1718 } |
| 1716 | 1719 |
| 1717 /// Defines all constructors for this class as ES5 constructors. | 1720 /// Defines all constructors for this class as ES5 constructors. |
| 1718 void _defineConstructors( | 1721 List<JS.Statement> _defineConstructors( |
| 1719 ClassElement classElem, | 1722 ClassElement classElem, |
| 1720 JS.Expression className, | 1723 JS.Expression className, |
| 1721 List<FieldDeclaration> fields, | 1724 List<FieldDeclaration> fields, |
| 1722 List<JS.Statement> body, | |
| 1723 List<ConstructorDeclaration> ctors) { | 1725 List<ConstructorDeclaration> ctors) { |
| 1724 // See if we have a "call" with a statically known function type: | 1726 // See if we have a "call" with a statically known function type: |
| 1725 // | 1727 // |
| 1726 // - if it's a method, then it does because all methods do, | 1728 // - if it's a method, then it does because all methods do, |
| 1727 // - if it's a getter, check the return type. | 1729 // - if it's a getter, check the return type. |
| 1728 // | 1730 // |
| 1729 // Other cases like a getter returning dynamic/Object/Function will be | 1731 // Other cases like a getter returning dynamic/Object/Function will be |
| 1730 // handled at runtime by the dynamic call mechanism. So we only | 1732 // handled at runtime by the dynamic call mechanism. So we only |
| 1731 // concern ourselves with statically known function types. | 1733 // concern ourselves with statically known function types. |
| 1732 // | 1734 // |
| 1733 // For the same reason, we can ignore "noSuchMethod". | 1735 // For the same reason, we can ignore "noSuchMethod". |
| 1734 // call-implemented-by-nSM will be dispatched by dcall at runtime. | 1736 // call-implemented-by-nSM will be dispatched by dcall at runtime. |
| 1735 bool isCallable = classElem.lookUpMethod('call', null) != null || | 1737 bool isCallable = classElem.lookUpMethod('call', null) != null || |
| 1736 classElem.lookUpGetter('call', null)?.returnType is FunctionType; | 1738 classElem.lookUpGetter('call', null)?.returnType is FunctionType; |
| 1737 | 1739 |
| 1740 var body = <JS.Statement>[]; |
| 1738 void addConstructor(ConstructorElement element, JS.Expression jsCtor) { | 1741 void addConstructor(ConstructorElement element, JS.Expression jsCtor) { |
| 1739 var ctorName = _constructorName(element); | 1742 var ctorName = _constructorName(element); |
| 1740 if (JS.invalidStaticFieldName(element.name)) { | 1743 if (JS.invalidStaticFieldName(element.name)) { |
| 1741 jsCtor = | 1744 jsCtor = |
| 1742 _callHelper('defineValue(#, #, #)', [className, ctorName, jsCtor]); | 1745 _callHelper('defineValue(#, #, #)', [className, ctorName, jsCtor]); |
| 1743 } else { | 1746 } else { |
| 1744 jsCtor = js.call('#.# = #', [className, ctorName, jsCtor]); | 1747 jsCtor = js.call('#.# = #', [className, ctorName, jsCtor]); |
| 1745 } | 1748 } |
| 1746 body.add(js.statement('#.prototype = #.prototype;', [jsCtor, className])); | 1749 body.add(js.statement('#.prototype = #.prototype;', [jsCtor, className])); |
| 1747 } | 1750 } |
| 1748 | 1751 |
| 1749 if (classElem.isMixinApplication) { | 1752 if (classElem.isMixinApplication) { |
| 1750 var supertype = classElem.supertype; | 1753 var supertype = classElem.supertype; |
| 1751 for (var ctor in classElem.constructors) { | 1754 for (var ctor in classElem.constructors) { |
| 1752 List<JS.Identifier> jsParams = _emitParametersForElement(ctor); | 1755 List<JS.Identifier> jsParams = _emitParametersForElement(ctor); |
| 1753 var superCtor = supertype.lookUpConstructor(ctor.name, ctor.library); | 1756 var superCtor = supertype.lookUpConstructor(ctor.name, ctor.library); |
| 1754 var superCall = | 1757 var superCall = |
| 1755 _superConstructorCall(classElem, className, superCtor, jsParams); | 1758 _superConstructorCall(classElem, className, superCtor, jsParams); |
| 1756 addConstructor( | 1759 addConstructor( |
| 1757 ctor, | 1760 ctor, |
| 1758 _finishConstructorFunction( | 1761 _finishConstructorFunction( |
| 1759 jsParams, | 1762 jsParams, |
| 1760 new JS.Block(superCall != null ? [superCall] : []), | 1763 new JS.Block(superCall != null ? [superCall] : []), |
| 1761 isCallable)); | 1764 isCallable)); |
| 1762 } | 1765 } |
| 1763 return; | 1766 return body; |
| 1764 } | 1767 } |
| 1765 | 1768 |
| 1766 // Iff no constructor is specified for a class C, it implicitly has a | 1769 // Iff no constructor is specified for a class C, it implicitly has a |
| 1767 // default constructor `C() : super() {}`, unless C is class Object. | 1770 // default constructor `C() : super() {}`, unless C is class Object. |
| 1768 if (ctors.isEmpty) { | 1771 if (ctors.isEmpty) { |
| 1769 var superCall = _superConstructorCall(classElem, className); | 1772 var superCall = _superConstructorCall(classElem, className); |
| 1770 List<JS.Statement> body = [_initializeFields(fields)]; | 1773 var ctorBody = <JS.Statement>[_initializeFields(fields)]; |
| 1771 if (superCall != null) body.add(superCall); | 1774 if (superCall != null) ctorBody.add(superCall); |
| 1772 | 1775 |
| 1773 addConstructor(classElem.unnamedConstructor, | 1776 addConstructor(classElem.unnamedConstructor, |
| 1774 _finishConstructorFunction([], new JS.Block(body), isCallable)); | 1777 _finishConstructorFunction([], new JS.Block(ctorBody), isCallable)); |
| 1775 return; | 1778 return body; |
| 1776 } | 1779 } |
| 1777 | 1780 |
| 1778 bool foundConstructor = false; | 1781 bool foundConstructor = false; |
| 1779 for (var ctor in ctors) { | 1782 for (var ctor in ctors) { |
| 1780 var element = ctor.element; | 1783 var element = ctor.element; |
| 1781 if (element.isFactory || _externalOrNative(ctor)) continue; | 1784 if (element.isFactory || _externalOrNative(ctor)) continue; |
| 1782 | 1785 |
| 1783 addConstructor( | 1786 addConstructor( |
| 1784 element, _emitConstructor(ctor, fields, isCallable, className)); | 1787 element, _emitConstructor(ctor, fields, isCallable, className)); |
| 1785 foundConstructor = true; | 1788 foundConstructor = true; |
| 1786 } | 1789 } |
| 1787 | 1790 |
| 1788 // If classElement has only factory constructors, and it can be mixed in, | 1791 // If classElement has only factory constructors, and it can be mixed in, |
| 1789 // then we need to emit a special hidden default constructor for use by | 1792 // then we need to emit a special hidden default constructor for use by |
| 1790 // mixins. | 1793 // mixins. |
| 1791 if (!foundConstructor && classElem.supertype.isObject) { | 1794 if (!foundConstructor && classElem.supertype.isObject) { |
| 1792 body.add( | 1795 body.add( |
| 1793 js.statement('(#[#] = function() { # }).prototype = #.prototype;', [ | 1796 js.statement('(#[#] = function() { # }).prototype = #.prototype;', [ |
| 1794 className, | 1797 className, |
| 1795 _callHelper('mixinNew'), | 1798 _callHelper('mixinNew'), |
| 1796 [_initializeFields(fields)], | 1799 [_initializeFields(fields)], |
| 1797 className | 1800 className |
| 1798 ])); | 1801 ])); |
| 1799 } | 1802 } |
| 1803 |
| 1804 return body; |
| 1800 } | 1805 } |
| 1801 | 1806 |
| 1802 /// Emits static fields for a class, and initialize them eagerly if possible, | 1807 /// Emits static fields for a class, and initialize them eagerly if possible, |
| 1803 /// otherwise define them as lazy properties. | 1808 /// otherwise define them as lazy properties. |
| 1804 void _emitStaticFields(List<FieldDeclaration> staticFields, | 1809 void _emitStaticFields(List<FieldDeclaration> staticFields, |
| 1805 ClassElement classElem, List<JS.Statement> body) { | 1810 ClassElement classElem, List<JS.Statement> body) { |
| 1806 var lazyStatics = staticFields.expand((f) => f.fields.variables).toList(); | 1811 var lazyStatics = staticFields.expand((f) => f.fields.variables).toList(); |
| 1807 if (lazyStatics.isNotEmpty) { | 1812 if (lazyStatics.isNotEmpty) { |
| 1808 body.add(_emitLazyFields(classElem, lazyStatics)); | 1813 body.add(_emitLazyFields(classElem, lazyStatics)); |
| 1809 } | 1814 } |
| (...skipping 4116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5926 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5931 if (targetIdentifier.staticElement is! PrefixElement) return false; |
| 5927 var prefix = targetIdentifier.staticElement as PrefixElement; | 5932 var prefix = targetIdentifier.staticElement as PrefixElement; |
| 5928 | 5933 |
| 5929 // The library the prefix is referring to must come from a deferred import. | 5934 // The library the prefix is referring to must come from a deferred import. |
| 5930 var containingLibrary = resolutionMap | 5935 var containingLibrary = resolutionMap |
| 5931 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 5936 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
| 5932 .library; | 5937 .library; |
| 5933 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5938 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 5934 return imports.length == 1 && imports[0].isDeferred; | 5939 return imports.length == 1 && imports[0].isDeferred; |
| 5935 } | 5940 } |
| OLD | NEW |