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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/lib/js_rti.dart

Issue 16538002: Move lib from sdk/lib/_internal/compiler/implementation to _internal root. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
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.
4
5 part of _js_helper;
6
7 setRuntimeTypeInfo(target, typeInfo) {
8 assert(typeInfo == null || typeInfo is JSArray);
9 // We have to check for null because factories may return null.
10 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
11 }
12
13 getRuntimeTypeInfo(target) {
14 if (target == null) return null;
15 return JS('var', r'#.$builtinTypeInfo', target);
16 }
17
18 getRuntimeTypeArgument(target, substitution, index) {
19 var arguments = substitute(substitution, getRuntimeTypeInfo(target));
20 return (arguments == null) ? null : getField(arguments, index);
21 }
22
23 class TypeImpl implements Type {
24 final String _typeName;
25
26 TypeImpl(this._typeName);
27
28 toString() => _typeName;
29
30 // TODO(ahe): This is a poor hashCode as it collides with its name.
31 int get hashCode => _typeName.hashCode;
32
33 bool operator ==(other) {
34 return (other is TypeImpl) && _typeName == other._typeName;
35 }
36 }
37
38 String getClassName(var object) {
39 return JS('String', r'#.constructor.builtin$cls', getInterceptor(object));
40 }
41
42 String getRuntimeTypeAsString(List runtimeType) {
43 String className = getConstructorName(runtimeType[0]);
44 return '$className${joinArguments(runtimeType, 1)}';
45 }
46
47 String getConstructorName(type) => JS('String', r'#.builtin$cls', type);
48
49 String runtimeTypeToString(type) {
50 if (type == null) {
51 return 'dynamic';
52 } else if (type is JSArray) {
53 // A list representing a type with arguments.
54 return getRuntimeTypeAsString(type);
55 } else {
56 // A reference to the constructor.
57 return getConstructorName(type);
58 }
59 }
60
61 String joinArguments(var types, int startIndex) {
62 if (types == null) return '';
63 bool firstArgument = true;
64 bool allDynamic = true;
65 StringBuffer buffer = new StringBuffer();
66 for (int index = startIndex; index < types.length; index++) {
67 if (firstArgument) {
68 firstArgument = false;
69 } else {
70 buffer.write(', ');
71 }
72 var argument = types[index];
73 if (argument != null) {
74 allDynamic = false;
75 }
76 buffer.write(runtimeTypeToString(argument));
77 }
78 return allDynamic ? '' : '<$buffer>';
79 }
80
81 String getRuntimeTypeString(var object) {
82 String className = object is JSArray ? 'List' : getClassName(object);
83 var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
84 return "$className${joinArguments(typeInfo, 0)}";
85 }
86
87 Type getRuntimeType(var object) {
88 String type = getRuntimeTypeString(object);
89 return new TypeImpl(type);
90 }
91
92 bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
93
94 Object invoke(function, arguments) {
95 return JS('var', r'#.apply(null, #)', function, arguments);
96 }
97
98 Object call(target, name) => JS('var', r'#[#]()', target, name);
99
100 substitute(var substitution, var arguments) {
101 if (substitution is JSArray) {
102 arguments = substitution;
103 } else if (isJsFunction(substitution)) {
104 arguments = invoke(substitution, arguments);
105 }
106 return arguments;
107 }
108
109 /**
110 * Perform a type check with arguments on the Dart object [object].
111 *
112 * Parameters:
113 * - [isField]: the name of the flag/function to check if the object
114 * is of the correct class.
115 * - [checks]: the (JavaScript) list of type representations for the
116 * arguments to check against.
117 * - [asField]: the name of the function that transforms the type
118 * arguments of [objects] to an instance of the class that we check
119 * against.
120 */
121 bool checkSubtype(Object object, String isField, List checks, String asField) {
122 if (object == null) return false;
123 var arguments = getRuntimeTypeInfo(object);
124 // Interceptor is needed for JSArray and native classes.
125 // TODO(sra): It could be a more specialized interceptor since [object] is not
126 // `null` or a primitive.
127 // TODO(9586): Move type info for static functions onto an interceptor.
128 var interceptor = getInterceptor(object);
129 bool isSubclass = getField(interceptor, isField);
130 // When we read the field and it is not there, [isSubclass] will be [:null:].
131 if (isSubclass == null || !isSubclass) return false;
132 // Should the asField function be passed the receiver?
133 var substitution = getField(interceptor, asField);
134 return checkArguments(substitution, arguments, checks);
135 }
136
137 String computeTypeName(String isField, List arguments) {
138 // Shorten the field name to the class name and append the textual
139 // representation of the type arguments.
140 int prefixLength = JS_OPERATOR_IS_PREFIX().length;
141 return Primitives.formatType(isField.substring(prefixLength, isField.length),
142 arguments);
143 }
144
145 Object subtypeCast(Object object, String isField, List checks, String asField) {
146 if (object != null && !checkSubtype(object, isField, checks, asField)) {
147 String actualType = Primitives.objectTypeName(object);
148 String typeName = computeTypeName(isField, checks);
149 throw new CastErrorImplementation(object, typeName);
150 }
151 return object;
152 }
153
154 Object assertSubtype(Object object, String isField, List checks,
155 String asField) {
156 if (object != null && !checkSubtype(object, isField, checks, asField)) {
157 String typeName = computeTypeName(isField, checks);
158 throw new TypeErrorImplementation(object, typeName);
159 }
160 return object;
161 }
162
163 /**
164 * Check that the types in the list [arguments] are subtypes of the types in
165 * list [checks] (at the respective positions), possibly applying [substitution]
166 * to the arguments before the check.
167 *
168 * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
169 * values for [substitution].
170 */
171 bool checkArguments(var substitution, var arguments, var checks) {
172 return areSubtypes(substitute(substitution, arguments), checks);
173 }
174
175 bool areSubtypes(List s, List t) {
176 // [:null:] means a raw type.
177 if (s == null || t == null) return true;
178
179 assert(s is JSArray);
180 assert(t is JSArray);
181 assert(s.length == t.length);
182
183 int len = s.length;
184 for (int i = 0; i < len; i++) {
185 if (!isSubtype(s[i], t[i])) {
186 return false;
187 }
188 }
189 return true;
190 }
191
192 getArguments(var type) {
193 return type is JSArray ? JS('var', r'#.slice(1)', type) : null;
194 }
195
196 getField(var object, var name) => JS('var', r'#[#]', object, name);
197
198 bool isSubtypeOfNull(type) {
199 // `null` means `dynamic`.
200 return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME();
201 }
202
203 /**
204 * Tests whether the Dart object [o] is a subtype of the runtime type
205 * representation [t], which is a type representation as described in the
206 * comment on [isSubtype].
207 */
208 bool checkSubtypeOfRuntimeType(Object o, var t) {
209 if (JS('bool', '# == null', o)) return isSubtypeOfNull(t);
210 if (JS('bool', '# == null', t)) return true;
211 // Get the runtime type information from the object here, because we may
212 // overwrite o with the interceptor below.
213 var rti = getRuntimeTypeInfo(o);
214 o = getInterceptor(o);
215 // We can use the object as its own type representation because we install
216 // the subtype flags and the substitution on the prototype, so they are
217 // properties of the object in JS.
218 var type;
219 if (JS('bool', '# != null', rti)) {
220 // If the type has type variables (that is, [:rti != null:]), make a copy of
221 // the type arguments and insert [o] in the first position to create a
222 // compound type representation.
223 type = JS('List', '#.slice()', rti);
224 JS('', '#.splice(0, 0, #)', type, o);
225 } else {
226 // Use the object as representation of the raw type.
227 type = o;
228 }
229 return isSubtype(type, t);
230 }
231
232 Object subtypeOfRuntimeTypeCast(Object object, var type) {
233 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
234 String actualType = Primitives.objectTypeName(object);
235 throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
236 }
237 return object;
238 }
239
240 Object assertSubtypeOfRuntimeType(Object object, var type) {
241 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
242 throw new TypeErrorImplementation(object, runtimeTypeToString(type));
243 }
244 return object;
245 }
246
247 /**
248 * Check whether the type represented by [s] is a subtype of the type
249 * represented by [t].
250 *
251 * Type representations can be:
252 * 1) a JavaScript constructor for a class C: the represented type is the raw
253 * type C.
254 * 2) a Dart object: this is the interceptor instance for a native type.
255 * 3) a JavaScript object: this represents a class for which there is no
256 * JavaScript constructor, because it is only used in type arguments or it
257 * is native. The represented type is the raw type of this class.
258 * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
259 * subtyping flags and the substitution of the type and the rest of the
260 * array are the type arguments.
261 * 5) [:null:]: the dynamic type.
262 */
263 bool isSubtype(var s, var t) {
264 // If either type is dynamic, [s] is a subtype of [t].
265 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
266 // Subtyping is reflexive.
267 if (JS('bool', '# === #', s, t)) return true;
268 // Get the object describing the class and check for the subtyping flag
269 // constructed from the type of [t].
270 var typeOfS = s is JSArray ? s[0] : s;
271 var typeOfT = t is JSArray ? t[0] : t;
272 // TODO(johnniwinther): replace this with the real function subtype test.
273 if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
274 return true;
275 }
276 // Check for a subtyping flag.
277 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
278 if (getField(typeOfS, test) == null) return false;
279 // Get the necessary substitution of the type arguments, if there is one.
280 var substitution;
281 if (JS('bool', '# !== #', typeOfT, typeOfS)) {
282 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
283 substitution = getField(typeOfS, field);
284 }
285 // The class of [s] is a subclass of the class of [t]. If [s] has no type
286 // arguments and no substitution, it is used as raw type. If [t] has no
287 // type arguments, it used as a raw type. In both cases, [s] is a subtype
288 // of [t].
289 if ((s is! JSArray && JS('bool', '# == null', substitution)) ||
290 t is! JSArray) {
291 return true;
292 }
293 // Recursively check the type arguments.
294 return checkArguments(substitution, getArguments(s), getArguments(t));
295 }
296
297 createRuntimeType(String name) => new TypeImpl(name);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698