OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of native; | 5 part of native; |
6 | 6 |
7 /// This class is a temporary work-around until we get a more powerful DartType. | 7 /// This class is a temporary work-around until we get a more powerful DartType. |
8 class SpecialType { | 8 class SpecialType { |
9 final String name; | 9 final String name; |
10 const SpecialType._(this.name); | 10 const SpecialType._(this.name); |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 resolver, | 638 resolver, |
639 isBuiltin: false, | 639 isBuiltin: false, |
640 validTags: const ['returns', 'creates']); | 640 validTags: const ['returns', 'creates']); |
641 | 641 |
642 return behavior; | 642 return behavior; |
643 } | 643 } |
644 | 644 |
645 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { | 645 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { |
646 FunctionType type = method.computeType(compiler.resolution); | 646 FunctionType type = method.computeType(compiler.resolution); |
647 var behavior = new NativeBehavior(); | 647 var behavior = new NativeBehavior(); |
648 behavior.typesReturned.add(type.returnType); | 648 var returnType = type.returnType; |
649 bool isInterop = compiler.backend.isJsInterop(method); | |
650 // Note: For dart:html and other internal libraries we maintain, we can | |
651 // trust the return type and use it to limit what we enqueue. We have to | |
652 // be more conservative about JS interop types and assume they can return | |
653 // anything (unless the user provides the experimental flag to trust the | |
654 // type of js-interop APIs). We do restrict the allocation effects and say | |
655 // that interop calls create only interop types (which may be unsound if | |
656 // an interop call returns a DOM type and declares a dynamic return type, | |
657 // but otherwise we would include a lot of code by default). | |
658 // TODO(sigmund,sra): consider doing something better for numeric types. | |
659 behavior.typesReturned.add( | |
660 !isInterop || compiler.trustJSInteropTypeAnnotations ? returnType | |
661 : const DynamicType()); | |
649 if (!type.returnType.isVoid) { | 662 if (!type.returnType.isVoid) { |
650 // Declared types are nullable. | 663 // Declared types are nullable. |
651 behavior.typesReturned.add(compiler.coreTypes.nullType); | 664 behavior.typesReturned.add(compiler.coreTypes.nullType); |
652 } | 665 } |
653 behavior._capture(type, compiler.resolution); | 666 behavior._capture(type, compiler.resolution, isInterop: isInterop, |
sra1
2015/12/01 00:38:07
break before isInterop
Siggi Cherem (dart-lang)
2015/12/01 00:43:54
Done.
| |
667 compiler: compiler); | |
654 | 668 |
655 // TODO(sra): Optional arguments are currently missing from the | 669 // TODO(sra): Optional arguments are currently missing from the |
656 // DartType. This should be fixed so the following work-around can be | 670 // DartType. This should be fixed so the following work-around can be |
657 // removed. | 671 // removed. |
658 method.functionSignature.forEachOptionalParameter( | 672 method.functionSignature.forEachOptionalParameter( |
659 (ParameterElement parameter) { | 673 (ParameterElement parameter) { |
660 behavior._escape(parameter.type, compiler.resolution); | 674 behavior._escape(parameter.type, compiler.resolution); |
661 }); | 675 }); |
662 | 676 |
663 behavior._overrideWithAnnotations(method, compiler); | 677 behavior._overrideWithAnnotations(method, compiler); |
664 return behavior; | 678 return behavior; |
665 } | 679 } |
666 | 680 |
667 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) { | 681 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) { |
668 Resolution resolution = compiler.resolution; | 682 Resolution resolution = compiler.resolution; |
669 DartType type = field.computeType(resolution); | 683 DartType type = field.computeType(resolution); |
670 var behavior = new NativeBehavior(); | 684 var behavior = new NativeBehavior(); |
671 behavior.typesReturned.add(type); | 685 bool isInterop = compiler.backend.isJsInterop(field); |
686 // TODO(sigmund,sra): consider doing something better for numeric types. | |
687 behavior.typesReturned.add( | |
688 !isInterop || compiler.trustJSInteropTypeAnnotations ? type | |
689 : const DynamicType()); | |
672 // Declared types are nullable. | 690 // Declared types are nullable. |
673 behavior.typesReturned.add(resolution.coreTypes.nullType); | 691 behavior.typesReturned.add(resolution.coreTypes.nullType); |
674 behavior._capture(type, resolution); | 692 behavior._capture(type, resolution, |
693 isInterop: isInterop, compiler: compiler); | |
675 behavior._overrideWithAnnotations(field, compiler); | 694 behavior._overrideWithAnnotations(field, compiler); |
676 return behavior; | 695 return behavior; |
677 } | 696 } |
678 | 697 |
679 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) { | 698 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) { |
680 Resolution resolution = compiler.resolution; | 699 Resolution resolution = compiler.resolution; |
681 DartType type = field.computeType(resolution); | 700 DartType type = field.computeType(resolution); |
682 var behavior = new NativeBehavior(); | 701 var behavior = new NativeBehavior(); |
683 behavior._escape(type, resolution); | 702 behavior._escape(type, resolution); |
684 // We don't override the default behaviour - the annotations apply to | 703 // We don't override the default behaviour - the annotations apply to |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
758 _escape(functionType.returnType, resolution); | 777 _escape(functionType.returnType, resolution); |
759 for (DartType parameter in functionType.parameterTypes) { | 778 for (DartType parameter in functionType.parameterTypes) { |
760 _capture(parameter, resolution); | 779 _capture(parameter, resolution); |
761 } | 780 } |
762 } | 781 } |
763 } | 782 } |
764 | 783 |
765 /// Models the behavior of Dart code receiving instances and methods of [type] | 784 /// Models the behavior of Dart code receiving instances and methods of [type] |
766 /// from native code. We usually start the analysis by capturing a native | 785 /// from native code. We usually start the analysis by capturing a native |
767 /// method that has been used. | 786 /// method that has been used. |
768 void _capture(DartType type, Resolution resolution) { | 787 /// |
788 /// We assume that JS-interop APIs cannot instantiate Dart types or | |
789 /// non-JSInterop native types. | |
790 void _capture(DartType type, Resolution resolution, | |
791 {bool isInterop: false, Compiler compiler}) { | |
769 type.computeUnaliased(resolution); | 792 type.computeUnaliased(resolution); |
770 type = type.unaliased; | 793 type = type.unaliased; |
771 if (type is FunctionType) { | 794 if (type is FunctionType) { |
772 FunctionType functionType = type; | 795 FunctionType functionType = type; |
773 _capture(functionType.returnType, resolution); | 796 _capture(functionType.returnType, resolution, |
797 isInterop: isInterop, compiler: compiler); | |
774 for (DartType parameter in functionType.parameterTypes) { | 798 for (DartType parameter in functionType.parameterTypes) { |
775 _escape(parameter, resolution); | 799 _escape(parameter, resolution); |
776 } | 800 } |
777 } else { | 801 } else { |
778 typesInstantiated.add(type); | 802 DartType instantiated = null; |
803 JavaScriptBackend backend = compiler?.backend; | |
804 if (!isInterop) { | |
805 typesInstantiated.add(type); | |
806 } else { | |
807 if (type.element != null && backend.isNative(type.element)) { | |
808 // Any declared native or interop type (isNative implies isJsInterop) | |
809 // is assumed to be allocated. | |
810 typesInstantiated.add(type); | |
811 } | |
812 | |
813 if (!compiler.trustJSInteropTypeAnnotations || | |
814 type.isDynamic || type.isObject) { | |
815 // By saying that only JS-interop types can be created, we prevent | |
816 // pulling in every other native type (e.g. all of dart:html) when a | |
817 // JS interop API returns dynamic or when we don't trust the type | |
818 // annotations. This means that to some degree we still use the return | |
819 // type to decide whether to include native types, even if we don't | |
820 // trust the type annotation. | |
821 typesInstantiated.add( | |
822 backend.helpers.jsJavaScriptObjectClass.thisType); | |
823 } else { | |
824 // Otherwise, when the declared type is a Dart type, we do not | |
825 // register an allocation because we assume it cannot be instantiated | |
826 // from within the JS-interop code. It must have escaped from another | |
827 // API. | |
828 } | |
829 } | |
779 } | 830 } |
780 } | 831 } |
781 | 832 |
782 static dynamic _parseType( | 833 static dynamic _parseType( |
783 String typeString, | 834 String typeString, |
784 Parsing parsing, | 835 Parsing parsing, |
785 lookup(name), | 836 lookup(name), |
786 locationNodeOrElement) { | 837 locationNodeOrElement) { |
787 DiagnosticReporter reporter = parsing.reporter; | 838 DiagnosticReporter reporter = parsing.reporter; |
788 if (typeString == '=Object') return SpecialType.JsObject; | 839 if (typeString == '=Object') return SpecialType.JsObject; |
(...skipping 21 matching lines...) Expand all Loading... | |
810 MessageKind.GENERIC, | 861 MessageKind.GENERIC, |
811 {'text': "Type '$typeString' not found."}); | 862 {'text': "Type '$typeString' not found."}); |
812 return const DynamicType(); | 863 return const DynamicType(); |
813 } | 864 } |
814 | 865 |
815 static _errorNode(locationNodeOrElement, Parsing parsing) { | 866 static _errorNode(locationNodeOrElement, Parsing parsing) { |
816 if (locationNodeOrElement is Node) return locationNodeOrElement; | 867 if (locationNodeOrElement is Node) return locationNodeOrElement; |
817 return locationNodeOrElement.parseNode(parsing); | 868 return locationNodeOrElement.parseNode(parsing); |
818 } | 869 } |
819 } | 870 } |
OLD | NEW |