Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1732)

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart

Issue 2962263002: fix #30030, fix #27327 - fix tearoffs and various Object member bugs (Closed)
Patch Set: fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 /// This library defines the representation of runtime types. 5 /// This library defines the representation of runtime types.
6 part of dart._runtime; 6 part of dart._runtime;
7 7
8 final metadata = JS('', 'Symbol("metadata")'); 8 final metadata = JS('', 'Symbol("metadata")');
9 9
10 /// The symbol used to store the cached `Type` object associated with a class. 10 /// The symbol used to store the cached `Type` object associated with a class.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 /// T.as(o): Implements 'o as T'. 49 /// T.as(o): Implements 'o as T'.
50 /// T._check(o): Implements the type assertion of 'T x = o;' 50 /// T._check(o): Implements the type assertion of 'T x = o;'
51 /// 51 ///
52 /// By convention, we used named JavaScript functions for these methods with the 52 /// By convention, we used named JavaScript functions for these methods with the
53 /// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the 53 /// name 'is_X', 'as_X' and 'check_X' for various X to indicate the type or the
54 /// implementation strategy for the test (e.g 'is_String', 'is_G' for generic 54 /// implementation strategy for the test (e.g 'is_String', 'is_G' for generic
55 /// types, etc.) 55 /// types, etc.)
56 // TODO(jmesserly): we shouldn't implement Type here. It should be moved down 56 // TODO(jmesserly): we shouldn't implement Type here. It should be moved down
57 // to AbstractFunctionType. 57 // to AbstractFunctionType.
58 class TypeRep implements Type { 58 class TypeRep implements Type {
59 TypeRep() {
60 _initialize;
61 }
62 String get name => this.toString(); 59 String get name => this.toString();
60
61 @JSExportName('is')
62 bool is_T(object) => instanceOf(object, this);
63
64 @JSExportName('as')
65 as_T(object) => cast(object, this);
66
67 @JSExportName('_check')
68 check_T(object) => check(object, this);
63 } 69 }
64 70
65 class Dynamic extends TypeRep { 71 class Dynamic extends TypeRep {
66 toString() => 'dynamic'; 72 toString() => 'dynamic';
73
74 @JSExportName('is')
75 bool is_T(object) => true;
76
77 @JSExportName('as')
78 as_T(object) => object;
79
80 @JSExportName('_check')
81 check_T(object) => object;
67 } 82 }
68 83
69 class LazyJSType extends TypeRep { 84 class LazyJSType extends TypeRep {
70 final _jsTypeCallback; 85 final Function() _rawJSType;
71 final _dartName; 86 final String _dartName;
72 87
73 LazyJSType(this._jsTypeCallback, this._dartName); 88 LazyJSType(this._rawJSType, this._dartName);
74 89
75 get _rawJSType => JS('', '#()', _jsTypeCallback); 90 toString() => typeName(_rawJSType());
76 91
77 toString() => _jsTypeCallback != null ? typeName(_rawJSType) : _dartName; 92 rawJSTypeForCheck() {
93 var raw = _rawJSType();
94 if (raw != null) return raw;
95 _warn('Cannot find native JavaScript type ($_dartName) for type check');
96 return _dynamic;
97 }
98
99 @JSExportName('is')
100 bool is_T(obj) => instanceOf(obj, rawJSTypeForCheck());
101
102 @JSExportName('as')
103 as_T(obj) => cast(obj, rawJSTypeForCheck());
104
105 @JSExportName('_check')
106 check_T(obj) => check(obj, rawJSTypeForCheck());
107 }
108
109 /// An anonymous JS type
110 ///
111 /// For the purposes of subtype checks, these match any JS type.
112 class AnonymousJSType extends TypeRep {
113 final String _dartName;
114 AnonymousJSType(this._dartName);
115 toString() => _dartName;
116
117 @JSExportName('is')
118 bool is_T(obj) => _isJSType(getReifiedType(obj));
119
120 @JSExportName('as')
121 as_T(obj) => is_T(obj) ? obj : cast(obj, this);
122
123 @JSExportName('_check')
124 check_T(obj) => is_T(obj) ? obj : check(obj, this);
78 } 125 }
79 126
80 void _warn(arg) { 127 void _warn(arg) {
81 JS('void', 'console.warn(#)', arg); 128 JS('void', 'console.warn(#)', arg);
82 } 129 }
83 130
84 _isInstanceOfLazyJSType(o, LazyJSType t) { 131 bool _isJSType(t) => JS('bool', '!#[dart._runtimeType]', t);
85 if (t._jsTypeCallback != null) { 132
86 if (t._rawJSType == null) { 133 var _lazyJSTypes = JS('', 'new Map()');
87 var expected = t._dartName; 134 var _anonymousJSTypes = JS('', 'new Map()');
88 var actual = typeName(getReifiedType(o)); 135
89 _warn('Cannot find native JavaScript type ($expected) ' 136 lazyJSType(Function() getJSTypeCallback, String name) {
90 'to type check $actual'); 137 var ret = JS('', '#.get(#)', _lazyJSTypes, name);
91 return true; 138 if (ret == null) {
92 } 139 ret = new LazyJSType(getJSTypeCallback, name);
93 return JS('bool', 'dart.is(#, #)', o, t._rawJSType); 140 JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
94 } 141 }
95 if (o == null) return false; 142 return ret;
96 // Anonymous case: match any JS type.
97 return _isJSObject(o);
98 } 143 }
99 144
100 _asInstanceOfLazyJSType(o, LazyJSType t) { 145 anonymousJSType(String name) {
101 if (t._jsTypeCallback != null) { 146 var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
102 if (t._rawJSType == null) { 147 if (ret == null) {
103 var expected = t._dartName; 148 ret = new AnonymousJSType(name);
104 var actual = typeName(getReifiedType(o)); 149 JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
105 _warn('Cannot find native JavaScript type ($expected) '
106 'to type check $actual');
107 return o;
108 }
109 return JS('bool', 'dart.as(#, #)', o, t._rawJSType);
110 } 150 }
111 // Anonymous case: allow any JS type. 151 return ret;
112 if (o == null) return null;
113 if (!_isJSObject(o)) _throwCastError(o, t, true);
114 return o;
115 } 152 }
116 153
117 bool _isJSObject(o) =>
118 JS('bool', '!dart.getReifiedType(#)[dart._runtimeType]', o);
119
120 bool _isJSType(t) => JS('bool', '!#[dart._runtimeType]', t);
121
122 @JSExportName('dynamic') 154 @JSExportName('dynamic')
123 final _dynamic = new Dynamic(); 155 final _dynamic = new Dynamic();
124 156
125 final _initialize = _initialize2();
126
127 _initialize2() => JS(
128 '',
129 '''(() => {
130 // JavaScript API forwards to runtime library.
131 $TypeRep.prototype.is = function is_T(object) {
132 return dart.is(object, this);
133 };
134 $TypeRep.prototype.as = function as_T(object) {
135 return dart.as(object, this);
136 };
137 $TypeRep.prototype._check = function check_T(object) {
138 return dart.check(object, this);
139 };
140
141 // Fast path for type `dynamic`.
142 $Dynamic.prototype.is = function is_Dynamic(object) {
143 return true;
144 };
145 $Dynamic.prototype.as = function as_Dynamic(object) {
146 return object;
147 };
148 $Dynamic.prototype._check = function check_Dynamic(object) {
149 return object;
150 };
151
152 $LazyJSType.prototype.is = function is_T(object) {
153 return $_isInstanceOfLazyJSType(object, this);
154 };
155 $LazyJSType.prototype.as = function as_T(object) {
156 return $_asInstanceOfLazyJSType(object, this);
157 };
158 $LazyJSType.prototype._check = function check_T(object) {
159 return $_asInstanceOfLazyJSType(object, this);
160 };
161 })()''');
162
163 class Void extends TypeRep { 157 class Void extends TypeRep {
164 toString() => 'void'; 158 toString() => 'void';
165 } 159 }
166 160
167 @JSExportName('void') 161 @JSExportName('void')
168 final _void = new Void(); 162 final _void = new Void();
169 163
170 class Bottom extends TypeRep { 164 class Bottom extends TypeRep {
171 toString() => 'bottom'; 165 toString() => 'bottom';
172 } 166 }
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 } 696 }
703 if (tag) return "Not a type: " + tag.name; 697 if (tag) return "Not a type: " + tag.name;
704 return "JSObject<" + $type.name + ">"; 698 return "JSObject<" + $type.name + ">";
705 })()'''); 699 })()''');
706 700
707 /// Returns `true` if we have a non-generic function type representation or the 701 /// Returns `true` if we have a non-generic function type representation or the
708 /// type for `Function`, which is a supertype of all functions in Dart. 702 /// type for `Function`, which is a supertype of all functions in Dart.
709 bool _isFunctionType(type) => JS('bool', '# instanceof # || # === #', type, 703 bool _isFunctionType(type) => JS('bool', '# instanceof # || # === #', type,
710 AbstractFunctionType, type, Function); 704 AbstractFunctionType, type, Function);
711 705
712 isLazyJSSubtype(t1, LazyJSType t2, isCovariant) {
713 // All JS types are subtypes of anonymous JS types.
714 if (t2._jsTypeCallback == null) {
715 return _isJSType(t1);
716 }
717 return _isSubtype(t1, t2._rawJSType, isCovariant);
718 }
719
720 /// Returns true if [ft1] <: [ft2]. 706 /// Returns true if [ft1] <: [ft2].
721 /// Returns false if [ft1] </: [ft2] in both spec and strong mode 707 /// Returns false if [ft1] </: [ft2] in both spec and strong mode
722 /// Returns null if [ft1] </: [ft2] in strong mode, but spec mode 708 /// Returns null if [ft1] </: [ft2] in strong mode, but spec mode
723 /// may differ 709 /// may differ
724 /// If [isCovariant] is true, then we are checking subtyping in a covariant 710 /// If [isCovariant] is true, then we are checking subtyping in a covariant
725 /// position, and hence the direction of the check for function types 711 /// position, and hence the direction of the check for function types
726 /// corresponds to the direction of the check according to the Dart spec. 712 /// corresponds to the direction of the check according to the Dart spec.
727 isFunctionSubtype(ft1, ft2, isCovariant) => JS( 713 isFunctionSubtype(ft1, ft2, isCovariant) => JS(
728 '', 714 '',
729 '''(() => { 715 '''(() => {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 870
885 // "Traditional" name-based subtype check. Avoid passing 871 // "Traditional" name-based subtype check. Avoid passing
886 // function types to the class subtype checks, since we don't 872 // function types to the class subtype checks, since we don't
887 // currently distinguish between generic typedefs and classes. 873 // currently distinguish between generic typedefs and classes.
888 if (!($t1 instanceof $AbstractFunctionType) && 874 if (!($t1 instanceof $AbstractFunctionType) &&
889 !($t2 instanceof $AbstractFunctionType)) { 875 !($t2 instanceof $AbstractFunctionType)) {
890 let result = $isClassSubType($t1, $t2, $isCovariant); 876 let result = $isClassSubType($t1, $t2, $isCovariant);
891 if (result === true || result === null) return result; 877 if (result === true || result === null) return result;
892 } 878 }
893 879
880 if ($t2 instanceof $AnonymousJSType) {
881 // All JS types are subtypes of anonymous JS types.
882 return $_isJSType($t1);
883 }
894 if ($t2 instanceof $LazyJSType) { 884 if ($t2 instanceof $LazyJSType) {
895 return $isLazyJSSubtype($t1, $t2, $isCovariant); 885 return $_isSubtype($t1, $t2.rawJSTypeForCheck(), isCovariant);
896 } 886 }
897 887
898 // Function subtyping. 888 // Function subtyping.
899 889
900 // Handle Objects with call methods. Those are functions 890 // Handle Objects with call methods. Those are functions
901 // even if they do not *nominally* subtype core.Function. 891 // even if they do not *nominally* subtype core.Function.
902 if (!$_isFunctionType($t1)) { 892 if (!$_isFunctionType($t1)) {
903 $t1 = $getMethodType($t1, 'call'); 893 $t1 = $getMethodType($t1, 'call');
904 if ($t1 == null) return false; 894 if ($t1 == null) return false;
905 } 895 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 return true; 1054 return true;
1065 } 1055 }
1066 1056
1067 let typeArgs = $getGenericArgs($type); 1057 let typeArgs = $getGenericArgs($type);
1068 if (!typeArgs) return true; 1058 if (!typeArgs) return true;
1069 for (let t of typeArgs) { 1059 for (let t of typeArgs) {
1070 if (t != $Object && t != $dynamic) return false; 1060 if (t != $Object && t != $dynamic) return false;
1071 } 1061 }
1072 return true; 1062 return true;
1073 })()'''); 1063 })()''');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698