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

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

Issue 806883002: dart2js: Minor cosmetic cleanups. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 6 years 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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 /** 5 /**
6 * This part contains helpers for supporting runtime type information. 6 * This part contains helpers for supporting runtime type information.
7 * 7 *
8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is 8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is
9 * used where we adopt the scheme of using explicit type annotation for Dart 9 * used where we adopt the scheme of using explicit type annotation for Dart
10 * objects and 'var' or omitted return type for JavaScript objects. 10 * objects and 'var' or omitted return type for JavaScript objects.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 final int bound; 76 final int bound;
77 77
78 const TypeVariable(this.owner, this.name, this.bound); 78 const TypeVariable(this.owner, this.name, this.bound);
79 } 79 }
80 80
81 getMangledTypeName(TypeImpl type) => type._typeName; 81 getMangledTypeName(TypeImpl type) => type._typeName;
82 82
83 /** 83 /**
84 * Sets the runtime type information on [target]. [typeInfo] is a type 84 * Sets the runtime type information on [target]. [typeInfo] is a type
85 * representation of type 4 or 5, that is, either a JavaScript array or 85 * representation of type 4 or 5, that is, either a JavaScript array or
86 * [:null:]. 86 * `null`.
87 */ 87 */
88 Object setRuntimeTypeInfo(Object target, var typeInfo) { 88 Object setRuntimeTypeInfo(Object target, var typeInfo) {
89 assert(isNull(typeInfo) || isJsArray(typeInfo)); 89 assert(typeInfo == null || isJsArray(typeInfo));
90 // We have to check for null because factories may return null. 90 // We have to check for null because factories may return null.
91 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo); 91 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
92 return target; 92 return target;
93 } 93 }
94 94
95 /** 95 /**
96 * Returns the runtime type information of [target]. The returned value is a 96 * Returns the runtime type information of [target]. The returned value is a
97 * list of type representations for the type arguments. 97 * list of type representations for the type arguments.
98 */ 98 */
99 getRuntimeTypeInfo(Object target) { 99 getRuntimeTypeInfo(Object target) {
(...skipping 10 matching lines...) Expand all
110 return substitute(substitution, getRuntimeTypeInfo(target)); 110 return substitute(substitution, getRuntimeTypeInfo(target));
111 } 111 }
112 112
113 /** 113 /**
114 * Returns the [index]th type argument of [target] as an instance of 114 * Returns the [index]th type argument of [target] as an instance of
115 * [substitutionName]. 115 * [substitutionName].
116 */ 116 */
117 @NoThrows() @NoSideEffects() @NoInline() 117 @NoThrows() @NoSideEffects() @NoInline()
118 getRuntimeTypeArgument(Object target, String substitutionName, int index) { 118 getRuntimeTypeArgument(Object target, String substitutionName, int index) {
119 var arguments = getRuntimeTypeArguments(target, substitutionName); 119 var arguments = getRuntimeTypeArguments(target, substitutionName);
120 return isNull(arguments) ? null : getIndex(arguments, index); 120 return arguments == null ? null : getIndex(arguments, index);
121 } 121 }
122 122
123 @NoThrows() @NoSideEffects() @NoInline() 123 @NoThrows() @NoSideEffects() @NoInline()
124 getTypeArgumentByIndex(Object target, int index) { 124 getTypeArgumentByIndex(Object target, int index) {
125 var rti = getRuntimeTypeInfo(target); 125 var rti = getRuntimeTypeInfo(target);
126 return isNull(rti) ? null : getIndex(rti, index); 126 return rti == null ? null : getIndex(rti, index);
127 } 127 }
128 128
129 void copyTypeArguments(Object source, Object target) { 129 void copyTypeArguments(Object source, Object target) {
130 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source); 130 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source);
131 } 131 }
132 132
133 /** 133 /**
134 * Retrieves the class name from type information stored on the constructor 134 * Retrieves the class name from type information stored on the constructor
135 * of [object]. 135 * of [object].
136 */ 136 */
(...skipping 16 matching lines...) Expand all
153 /** 153 /**
154 * Retrieves the class name from type information stored on the constructor 154 * Retrieves the class name from type information stored on the constructor
155 * [type]. 155 * [type].
156 */ 156 */
157 String getConstructorName(var type) => JS('String', r'#.builtin$cls', type); 157 String getConstructorName(var type) => JS('String', r'#.builtin$cls', type);
158 158
159 /** 159 /**
160 * Returns a human-readable representation of the type representation [type]. 160 * Returns a human-readable representation of the type representation [type].
161 */ 161 */
162 String runtimeTypeToString(var type, {String onTypeVariable(int i)}) { 162 String runtimeTypeToString(var type, {String onTypeVariable(int i)}) {
163 if (isNull(type)) { 163 if (type == null) {
164 return 'dynamic'; 164 return 'dynamic';
165 } else if (isJsArray(type)) { 165 } else if (isJsArray(type)) {
166 // A list representing a type with arguments. 166 // A list representing a type with arguments.
167 return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable); 167 return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable);
168 } else if (isJsFunction(type)) { 168 } else if (isJsFunction(type)) {
169 // A reference to the constructor. 169 // A reference to the constructor.
170 return getConstructorName(type); 170 return getConstructorName(type);
171 } else if (type is int) { 171 } else if (type is int) {
172 if (onTypeVariable == null) { 172 if (onTypeVariable == null) {
173 return type.toString(); 173 return type.toString();
174 } else { 174 } else {
175 return onTypeVariable(type); 175 return onTypeVariable(type);
176 } 176 }
177 } else { 177 } else {
178 // TODO(ahe): Handle function types, and be sure to always return a string. 178 // TODO(ahe): Handle function types, and be sure to always return a string.
179 return null; 179 return null;
180 } 180 }
181 } 181 }
182 182
183 /** 183 /**
184 * Creates a comma-separated string of human-readable representations of the 184 * Creates a comma-separated string of human-readable representations of the
185 * type representations in the JavaScript array [types] starting at index 185 * type representations in the JavaScript array [types] starting at index
186 * [startIndex]. 186 * [startIndex].
187 */ 187 */
188 String joinArguments(var types, int startIndex, 188 String joinArguments(var types, int startIndex,
189 {String onTypeVariable(int i)}) { 189 {String onTypeVariable(int i)}) {
190 if (isNull(types)) return ''; 190 if (types == null) return '';
191 assert(isJsArray(types)); 191 assert(isJsArray(types));
192 bool firstArgument = true; 192 bool firstArgument = true;
193 bool allDynamic = true; 193 bool allDynamic = true;
194 StringBuffer buffer = new StringBuffer(); 194 StringBuffer buffer = new StringBuffer();
195 for (int index = startIndex; index < getLength(types); index++) { 195 for (int index = startIndex; index < getLength(types); index++) {
196 if (firstArgument) { 196 if (firstArgument) {
197 firstArgument = false; 197 firstArgument = false;
198 } else { 198 } else {
199 buffer.write(', '); 199 buffer.write(', ');
200 } 200 }
(...skipping 23 matching lines...) Expand all
224 return new TypeImpl(type); 224 return new TypeImpl(type);
225 } 225 }
226 226
227 /** 227 /**
228 * Applies the [substitution] on the [arguments]. 228 * Applies the [substitution] on the [arguments].
229 * 229 *
230 * See the comment in the beginning of this file for a description of the 230 * See the comment in the beginning of this file for a description of the
231 * possible values for [substitution]. 231 * possible values for [substitution].
232 */ 232 */
233 substitute(var substitution, var arguments) { 233 substitute(var substitution, var arguments) {
234 assert(isNull(substitution) || 234 assert(substitution == null ||
235 isJsFunction(substitution)); 235 isJsFunction(substitution));
236 assert(isNull(arguments) || isJsArray(arguments)); 236 assert(arguments == null || isJsArray(arguments));
237 if (isJsFunction(substitution)) { 237 if (isJsFunction(substitution)) {
238 substitution = invoke(substitution, arguments); 238 substitution = invoke(substitution, arguments);
239 if (isJsArray(substitution)) { 239 if (isJsArray(substitution)) {
240 arguments = substitution; 240 arguments = substitution;
241 } else if (isJsFunction(substitution)) { 241 } else if (isJsFunction(substitution)) {
242 // TODO(johnniwinther): Check if this is still needed. 242 // TODO(johnniwinther): Check if this is still needed.
243 arguments = invoke(substitution, arguments); 243 arguments = invoke(substitution, arguments);
244 } 244 }
245 } 245 }
246 return arguments; 246 return arguments;
(...skipping 13 matching lines...) Expand all
260 */ 260 */
261 bool checkSubtype(Object object, String isField, List checks, String asField) { 261 bool checkSubtype(Object object, String isField, List checks, String asField) {
262 if (object == null) return false; 262 if (object == null) return false;
263 var arguments = getRuntimeTypeInfo(object); 263 var arguments = getRuntimeTypeInfo(object);
264 // Interceptor is needed for JSArray and native classes. 264 // Interceptor is needed for JSArray and native classes.
265 // TODO(sra): It could be a more specialized interceptor since [object] is not 265 // TODO(sra): It could be a more specialized interceptor since [object] is not
266 // `null` or a primitive. 266 // `null` or a primitive.
267 // TODO(9586): Move type info for static functions onto an interceptor. 267 // TODO(9586): Move type info for static functions onto an interceptor.
268 var interceptor = getInterceptor(object); 268 var interceptor = getInterceptor(object);
269 var isSubclass = getField(interceptor, isField); 269 var isSubclass = getField(interceptor, isField);
270 // When we read the field and it is not there, [isSubclass] will be [:null:]. 270 // When we read the field and it is not there, [isSubclass] will be `null`.
271 if (isNull(isSubclass)) return false; 271 if (isSubclass == null) return false;
272 // Should the asField function be passed the receiver? 272 // Should the asField function be passed the receiver?
273 var substitution = getField(interceptor, asField); 273 var substitution = getField(interceptor, asField);
274 return checkArguments(substitution, arguments, checks); 274 return checkArguments(substitution, arguments, checks);
275 } 275 }
276 276
277 /// Returns the field's type name. 277 /// Returns the field's type name.
278 /// 278 ///
279 /// In minified mode, uses the unminified names if available. 279 /// In minified mode, uses the unminified names if available.
280 String computeTypeName(String isField, List arguments) { 280 String computeTypeName(String isField, List arguments) {
281 // Shorten the field name to the class name and append the textual 281 // Shorten the field name to the class name and append the textual
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 * See the comment in the beginning of this file for a description of the 325 * See the comment in the beginning of this file for a description of the
326 * possible values for [substitution]. 326 * possible values for [substitution].
327 */ 327 */
328 bool checkArguments(var substitution, var arguments, var checks) { 328 bool checkArguments(var substitution, var arguments, var checks) {
329 return areSubtypes(substitute(substitution, arguments), checks); 329 return areSubtypes(substitute(substitution, arguments), checks);
330 } 330 }
331 331
332 /** 332 /**
333 * Checks whether the types of [s] are all subtypes of the types of [t]. 333 * Checks whether the types of [s] are all subtypes of the types of [t].
334 * 334 *
335 * [s] and [t] are either [:null:] or JavaScript arrays of type representations, 335 * [s] and [t] are either `null` or JavaScript arrays of type representations,
336 * A [:null:] argument is interpreted as the arguments of a raw type, that is a 336 * A `null` argument is interpreted as the arguments of a raw type, that is a
337 * list of [:dynamic:]. If [s] and [t] are JavaScript arrays they must be of the 337 * list of `dynamic`. If [s] and [t] are JavaScript arrays they must be of the
338 * same length. 338 * same length.
339 * 339 *
340 * See the comment in the beginning of this file for a description of type 340 * See the comment in the beginning of this file for a description of type
341 * representations. 341 * representations.
342 */ 342 */
343 bool areSubtypes(var s, var t) { 343 bool areSubtypes(var s, var t) {
344 // [:null:] means a raw type. 344 // `null` means a raw type.
345 if (isNull(s) || isNull(t)) return true; 345 if (s == null || t == null) return true;
346 346
347 assert(isJsArray(s)); 347 assert(isJsArray(s));
348 assert(isJsArray(t)); 348 assert(isJsArray(t));
349 assert(getLength(s) == getLength(t)); 349 assert(getLength(s) == getLength(t));
350 350
351 int len = getLength(s); 351 int len = getLength(s);
352 for (int i = 0; i < len; i++) { 352 for (int i = 0; i < len; i++) {
353 if (!isSubtype(getIndex(s, i), getIndex(t, i))) { 353 if (!isSubtype(getIndex(s, i), getIndex(t, i))) {
354 return false; 354 return false;
355 } 355 }
356 } 356 }
357 return true; 357 return true;
358 } 358 }
359 359
360 /** 360 /**
361 * Computes the signature by applying the type arguments of [context] as an 361 * Computes the signature by applying the type arguments of [context] as an
362 * instance of [contextName] to the signature function [signature]. 362 * instance of [contextName] to the signature function [signature].
363 */ 363 */
364 computeSignature(var signature, var context, var contextName) { 364 computeSignature(var signature, var context, var contextName) {
365 var typeArguments = getRuntimeTypeArguments(context, contextName); 365 var typeArguments = getRuntimeTypeArguments(context, contextName);
366 return invokeOn(signature, context, typeArguments); 366 return invokeOn(signature, context, typeArguments);
367 } 367 }
368 368
369 /** 369 /**
370 * Returns [:true:] if the runtime type representation [type] is a supertype of 370 * Returns `true` if the runtime type representation [type] is a supertype of
371 * [:Null:]. 371 * [Null].
372 */ 372 */
373 bool isSupertypeOfNull(var type) { 373 bool isSupertypeOfNull(var type) {
374 // `null` means `dynamic`. 374 // `null` means `dynamic`.
375 return isNull(type) || getConstructorName(type) == JS_OBJECT_CLASS_NAME() 375 return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME()
376 || getConstructorName(type) == JS_NULL_CLASS_NAME(); 376 || getConstructorName(type) == JS_NULL_CLASS_NAME();
377 } 377 }
378 378
379 /** 379 /**
380 * Tests whether the Dart object [o] is a subtype of the runtime type 380 * Tests whether the Dart object [o] is a subtype of the runtime type
381 * representation [t]. 381 * representation [t].
382 * 382 *
383 * See the comment in the beginning of this file for a description of type 383 * See the comment in the beginning of this file for a description of type
384 * representations. 384 * representations.
385 */ 385 */
386 bool checkSubtypeOfRuntimeType(o, t) { 386 bool checkSubtypeOfRuntimeType(o, t) {
387 if (isNull(o)) return isSupertypeOfNull(t); 387 if (o == null) return isSupertypeOfNull(t);
388 if (isNull(t)) return true; 388 if (t == null) return true;
389 // Get the runtime type information from the object here, because we may 389 // Get the runtime type information from the object here, because we may
390 // overwrite o with the interceptor below. 390 // overwrite o with the interceptor below.
391 var rti = getRuntimeTypeInfo(o); 391 var rti = getRuntimeTypeInfo(o);
392 o = getInterceptor(o); 392 o = getInterceptor(o);
393 var type = JS('', '#.constructor', o); 393 var type = JS('', '#.constructor', o);
394 if (isNotNull(rti)) { 394 if (rti != null) {
395 // If the type has type variables (that is, [:rti != null:]), make a copy of 395 // If the type has type variables (that is, `rti != null`), make a copy of
396 // the type arguments and insert [o] in the first position to create a 396 // the type arguments and insert [o] in the first position to create a
397 // compound type representation. 397 // compound type representation.
398 rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy. 398 rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy.
399 JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0. 399 JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0.
400 type = rti; 400 type = rti;
401 } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { 401 } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) {
402 // Functions are treated specially and have their type information stored 402 // Functions are treated specially and have their type information stored
403 // directly in the instance. 403 // directly in the instance.
404 var signatureName = 404 var signatureName =
405 '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}'; 405 '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}';
406 if (hasField(o, signatureName)) return true; 406 if (hasField(o, signatureName)) return true;
407 var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}'); 407 var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}');
408 if (isNull(targetSignatureFunction)) return false; 408 if (targetSignatureFunction == null) return false;
409 type = invokeOn(targetSignatureFunction, o, null); 409 type = invokeOn(targetSignatureFunction, o, null);
410 return isFunctionSubtype(type, t); 410 return isFunctionSubtype(type, t);
411 } 411 }
412 return isSubtype(type, t); 412 return isSubtype(type, t);
413 } 413 }
414 414
415 Object subtypeOfRuntimeTypeCast(Object object, var type) { 415 Object subtypeOfRuntimeTypeCast(Object object, var type) {
416 if (object != null && !checkSubtypeOfRuntimeType(object, type)) { 416 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
417 String actualType = Primitives.objectTypeName(object); 417 String actualType = Primitives.objectTypeName(object);
418 throw new CastErrorImplementation(actualType, runtimeTypeToString(type)); 418 throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
419 } 419 }
420 return object; 420 return object;
421 } 421 }
422 422
423 Object assertSubtypeOfRuntimeType(Object object, var type) { 423 Object assertSubtypeOfRuntimeType(Object object, var type) {
424 if (object != null && !checkSubtypeOfRuntimeType(object, type)) { 424 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
425 throw new TypeErrorImplementation(object, runtimeTypeToString(type)); 425 throw new TypeErrorImplementation(object, runtimeTypeToString(type));
426 } 426 }
427 return object; 427 return object;
428 } 428 }
429 429
430 /** 430 /**
431 * Extracts the type arguments from a type representation. The result is a 431 * Extracts the type arguments from a type representation. The result is a
432 * JavaScript array or [:null:]. 432 * JavaScript array or `null`.
433 */ 433 */
434 getArguments(var type) { 434 getArguments(var type) {
435 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null; 435 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
436 } 436 }
437 437
438 /** 438 /**
439 * Checks whether the type represented by the type representation [s] is a 439 * Checks whether the type represented by the type representation [s] is a
440 * subtype of the type represented by the type representation [t]. 440 * subtype of the type represented by the type representation [t].
441 * 441 *
442 * See the comment in the beginning of this file for a description of type 442 * See the comment in the beginning of this file for a description of type
443 * representations. 443 * representations.
444 * 444 *
445 * The arguments [s] and [t] must be types, usually represented by the 445 * The arguments [s] and [t] must be types, usually represented by the
446 * constructor of the class, or an array (for generic types). 446 * constructor of the class, or an array (for generic types).
447 */ 447 */
448 bool isSubtype(var s, var t) { 448 bool isSubtype(var s, var t) {
449 // Subtyping is reflexive. 449 // Subtyping is reflexive.
450 if (isIdentical(s, t)) return true; 450 if (isIdentical(s, t)) return true;
451 // If either type is dynamic, [s] is a subtype of [t]. 451 // If either type is dynamic, [s] is a subtype of [t].
452 if (isNull(s) || isNull(t)) return true; 452 if (s == null || t == null) return true;
453 if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { 453 if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) {
454 return isFunctionSubtype(s, t); 454 return isFunctionSubtype(s, t);
455 } 455 }
456 // Check function types against the Function class. 456 // Check function types against the Function class.
457 if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { 457 if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) {
458 return getConstructorName(t) == JS_FUNCTION_CLASS_NAME(); 458 return getConstructorName(t) == JS_FUNCTION_CLASS_NAME();
459 } 459 }
460 460
461 // Get the object describing the class and check for the subtyping flag 461 // Get the object describing the class and check for the subtyping flag
462 // constructed from the type of [t]. 462 // constructed from the type of [t].
463 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; 463 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s;
464 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; 464 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t;
465 // Check for a subtyping flag. 465 // Check for a subtyping flag.
466 var name = runtimeTypeToString(typeOfT); 466 var name = runtimeTypeToString(typeOfT);
467 // Get the necessary substitution of the type arguments, if there is one. 467 // Get the necessary substitution of the type arguments, if there is one.
468 var substitution; 468 var substitution;
469 if (isNotIdentical(typeOfT, typeOfS)) { 469 if (isNotIdentical(typeOfT, typeOfS)) {
470 var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; 470 var test = '${JS_OPERATOR_IS_PREFIX()}${name}';
471 var typeOfSPrototype = JS('', '#.prototype', typeOfS); 471 var typeOfSPrototype = JS('', '#.prototype', typeOfS);
472 if (hasNoField(typeOfSPrototype, test)) return false; 472 if (hasNoField(typeOfSPrototype, test)) return false;
473 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 473 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
474 substitution = getField(typeOfSPrototype, field); 474 substitution = getField(typeOfSPrototype, field);
475 } 475 }
476 // The class of [s] is a subclass of the class of [t]. If [s] has no type 476 // The class of [s] is a subclass of the class of [t]. If [s] has no type
477 // arguments and no substitution, it is used as raw type. If [t] has no 477 // arguments and no substitution, it is used as raw type. If [t] has no
478 // type arguments, it used as a raw type. In both cases, [s] is a subtype 478 // type arguments, it used as a raw type. In both cases, [s] is a subtype
479 // of [t]. 479 // of [t].
480 if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) { 480 if ((!isJsArray(s) && substitution == null) || !isJsArray(t)) {
481 return true; 481 return true;
482 } 482 }
483 // Recursively check the type arguments. 483 // Recursively check the type arguments.
484 return checkArguments(substitution, getArguments(s), getArguments(t)); 484 return checkArguments(substitution, getArguments(s), getArguments(t));
485 } 485 }
486 486
487 bool isAssignable(var s, var t) { 487 bool isAssignable(var s, var t) {
488 return isSubtype(s, t) || isSubtype(t, s); 488 return isSubtype(s, t) || isSubtype(t, s);
489 } 489 }
490 490
491 /** 491 /**
492 * If [allowShorter] is [:true:], [t] is allowed to be shorter than [s]. 492 * If [allowShorter] is `true`, [t] is allowed to be shorter than [s].
493 */ 493 */
494 bool areAssignable(List s, List t, bool allowShorter) { 494 bool areAssignable(List s, List t, bool allowShorter) {
495 // Both lists are empty and thus equal. 495 // Both lists are empty and thus equal.
496 if (isNull(t) && isNull(s)) return true; 496 if (t ==null && s == null) return true;
497 // [t] is empty (and [s] is not) => only OK if [allowShorter]. 497 // [t] is empty (and [s] is not) => only OK if [allowShorter].
498 if (isNull(t)) return allowShorter; 498 if (t == null) return allowShorter;
499 // [s] is empty (and [t] is not) => [s] is not longer or equal to [t]. 499 // [s] is empty (and [t] is not) => [s] is not longer or equal to [t].
500 if (isNull(s)) return false; 500 if (s == null) return false;
501 501
502 assert(isJsArray(s)); 502 assert(isJsArray(s));
503 assert(isJsArray(t)); 503 assert(isJsArray(t));
504 504
505 int sLength = getLength(s); 505 int sLength = getLength(s);
506 int tLength = getLength(t); 506 int tLength = getLength(t);
507 if (allowShorter) { 507 if (allowShorter) {
508 if (sLength < tLength) return false; 508 if (sLength < tLength) return false;
509 } else { 509 } else {
510 if (sLength != tLength) return false; 510 if (sLength != tLength) return false;
511 } 511 }
512 512
513 for (int i = 0; i < tLength; i++) { 513 for (int i = 0; i < tLength; i++) {
514 if (!isAssignable(getIndex(s, i), getIndex(t, i))) { 514 if (!isAssignable(getIndex(s, i), getIndex(t, i))) {
515 return false; 515 return false;
516 } 516 }
517 } 517 }
518 return true; 518 return true;
519 } 519 }
520 520
521 bool areAssignableMaps(var s, var t) { 521 bool areAssignableMaps(var s, var t) {
522 if (isNull(t)) return true; 522 if (t == null) return true;
523 if (isNull(s)) return false; 523 if (s == null) return false;
524 524
525 assert(isJsObject(s)); 525 assert(isJsObject(s));
526 assert(isJsObject(t)); 526 assert(isJsObject(t));
527 527
528 List names = 528 List names =
529 JSArray.markFixedList(JS('', 'Object.getOwnPropertyNames(#)', t)); 529 JSArray.markFixedList(JS('', 'Object.getOwnPropertyNames(#)', t));
530 for (int i = 0; i < names.length; i++) { 530 for (int i = 0; i < names.length; i++) {
531 var name = names[i]; 531 var name = names[i];
532 if (JS('bool', '!Object.hasOwnProperty.call(#, #)', s, name)) { 532 if (JS('bool', '!Object.hasOwnProperty.call(#, #)', s, name)) {
533 return false; 533 return false;
(...skipping 21 matching lines...) Expand all
555 var sParameterTypes = 555 var sParameterTypes =
556 getField(s, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}'); 556 getField(s, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
557 var tParameterTypes = 557 var tParameterTypes =
558 getField(t, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}'); 558 getField(t, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
559 559
560 var sOptionalParameterTypes = 560 var sOptionalParameterTypes =
561 getField(s, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}'); 561 getField(s, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
562 var tOptionalParameterTypes = 562 var tOptionalParameterTypes =
563 getField(t, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}'); 563 getField(t, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
564 564
565 int sParametersLen = 565 int sParametersLen = sParameterTypes != null ? getLength(sParameterTypes) : 0;
566 isNotNull(sParameterTypes) ? getLength(sParameterTypes) : 0; 566 int tParametersLen = tParameterTypes != null ? getLength(tParameterTypes) : 0;
567 int tParametersLen =
568 isNotNull(tParameterTypes) ? getLength(tParameterTypes) : 0;
569 567
570 int sOptionalParametersLen = isNotNull(sOptionalParameterTypes) 568 int sOptionalParametersLen =
571 ? getLength(sOptionalParameterTypes) : 0; 569 sOptionalParameterTypes != null ? getLength(sOptionalParameterTypes) : 0;
572 int tOptionalParametersLen = isNotNull(tOptionalParameterTypes) 570 int tOptionalParametersLen =
573 ? getLength(tOptionalParameterTypes) : 0; 571 tOptionalParameterTypes != null ? getLength(tOptionalParameterTypes) : 0;
574 572
575 if (sParametersLen > tParametersLen) { 573 if (sParametersLen > tParametersLen) {
576 // Too many required parameters in [s]. 574 // Too many required parameters in [s].
577 return false; 575 return false;
578 } 576 }
579 if (sParametersLen + sOptionalParametersLen < 577 if (sParametersLen + sOptionalParametersLen <
580 tParametersLen + tOptionalParametersLen) { 578 tParametersLen + tOptionalParametersLen) {
581 // Too few required and optional parameters in [s]. 579 // Too few required and optional parameters in [s].
582 return false; 580 return false;
583 } 581 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 619
622 var sNamedParameters = 620 var sNamedParameters =
623 getField(s, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}'); 621 getField(s, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
624 var tNamedParameters = 622 var tNamedParameters =
625 getField(t, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}'); 623 getField(t, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
626 return areAssignableMaps(sNamedParameters, tNamedParameters); 624 return areAssignableMaps(sNamedParameters, tNamedParameters);
627 } 625 }
628 626
629 /** 627 /**
630 * Calls the JavaScript [function] with the [arguments] with the global scope 628 * Calls the JavaScript [function] with the [arguments] with the global scope
631 * as the [:this:] context. 629 * as the `this` context.
632 */ 630 */
633 invoke(var function, var arguments) => invokeOn(function, null, arguments); 631 invoke(var function, var arguments) => invokeOn(function, null, arguments);
634 632
635 /** 633 /**
636 * Calls the JavaScript [function] with the [arguments] with [receiver] as the 634 * Calls the JavaScript [function] with the [arguments] with [receiver] as the
637 * [:this:] context. 635 * `this` context.
638 */ 636 */
639 Object invokeOn(function, receiver, arguments) { 637 Object invokeOn(function, receiver, arguments) {
640 assert(isJsFunction(function)); 638 assert(isJsFunction(function));
641 assert(isNull(arguments) || isJsArray(arguments)); 639 assert(arguments == null || isJsArray(arguments));
642 return JS('var', r'#.apply(#, #)', function, receiver, arguments); 640 return JS('var', r'#.apply(#, #)', function, receiver, arguments);
643 } 641 }
644 642
645 /// Calls the property [name] on the JavaScript [object]. 643 /// Calls the property [name] on the JavaScript [object].
646 call(var object, String name) => JS('var', r'#[#]()', object, name); 644 call(var object, String name) => JS('var', r'#[#]()', object, name);
647 645
648 /// Returns the property [name] of the JavaScript object [object]. 646 /// Returns the property [name] of the JavaScript object [object].
649 getField(var object, String name) => JS('var', r'#[#]', object, name); 647 getField(var object, String name) => JS('var', r'#[#]', object, name);
650 648
651 /// Returns the property [index] of the JavaScript array [array]. 649 /// Returns the property [index] of the JavaScript array [array].
(...skipping 10 matching lines...) Expand all
662 660
663 /// Returns whether [value] is a JavaScript array. 661 /// Returns whether [value] is a JavaScript array.
664 bool isJsArray(var value) { 662 bool isJsArray(var value) {
665 return value is JSArray; 663 return value is JSArray;
666 } 664 }
667 665
668 hasField(var object, var name) => JS('bool', r'# in #', name, object); 666 hasField(var object, var name) => JS('bool', r'# in #', name, object);
669 667
670 hasNoField(var object, var name) => !hasField(object, name); 668 hasNoField(var object, var name) => !hasField(object, name);
671 669
672 /// Returns [:true:] if [o] is a JavaScript function. 670 /// Returns `true` if [o] is a JavaScript function.
673 bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o); 671 bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
674 672
675 /// Returns [:true:] if [o] is a JavaScript object. 673 /// Returns `true` if [o] is a JavaScript object.
676 bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o); 674 bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o);
677 675
678 /** 676 /**
679 * Returns [:true:] if [o] is equal to [:null:], that is either [:null:] or 677 * Returns `true` if the JavaScript values [s] and [t] are identical. We use
680 * [:undefined:]. We use this helper to avoid generating code under the invalid 678 * this helper instead of [identical] because `identical` needs to merge
681 * assumption that [o] is a Dart value. 679 * `null` and `undefined` (which we can avoid).
682 */
683 bool isNull(var o) => JS('bool', '# == null', o);
684
685 /**
686 * Returns [:true:] if [o] is not equal to [:null:], that is neither [:null:]
687 * nor [:undefined:]. We use this helper to avoid generating code under the
688 * invalid assumption that [o] is a Dart value.
689 */
690 bool isNotNull(var o) => JS('bool', '# != null', o);
691
692 /**
693 * Returns [:true:] if the JavaScript values [s] and [t] are identical. We use
694 * this helper to avoid generating code under the invalid assumption that [s]
695 * and [t] are Dart values.
696 */ 680 */
697 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); 681 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
698 682
699 /** 683 /**
700 * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We 684 * Returns `true` if the JavaScript values [s] and [t] are not identical. We use
701 * use this helper to avoid generating code under the invalid assumption that 685 * this helper instead of [identical] because `identical` needs to merge
702 * [s] and [t] are Dart values. 686 * `null` and `undefined` (which we can avoid).
703 */ 687 */
704 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); 688 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698