OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #library('dart:_js_helper'); | 5 #library('dart:_js_helper'); |
6 | 6 |
7 #import('dart:collection'); | 7 #import('dart:collection'); |
8 | 8 |
9 #source('constant_map.dart'); | 9 #source('constant_map.dart'); |
10 #source('native_helper.dart'); | 10 #source('native_helper.dart'); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 295 |
296 index$slow(var a, var index) { | 296 index$slow(var a, var index) { |
297 if (a is String || isJsArray(a)) { | 297 if (a is String || isJsArray(a)) { |
298 if (index is !int) { | 298 if (index is !int) { |
299 if (index is !num) throw new ArgumentError(index); | 299 if (index is !num) throw new ArgumentError(index); |
300 if (!identical(index.truncate(), index)) throw new ArgumentError(index); | 300 if (!identical(index.truncate(), index)) throw new ArgumentError(index); |
301 } | 301 } |
302 if (index < 0 || index >= a.length) { | 302 if (index < 0 || index >= a.length) { |
303 throw new RangeError.value(index); | 303 throw new RangeError.value(index); |
304 } | 304 } |
305 return JS('Object', r'#[#]', a, index); | 305 return JS('', r'#[#]', a, index); |
306 } | 306 } |
307 return UNINTERCEPTED(a[index]); | 307 return UNINTERCEPTED(a[index]); |
308 } | 308 } |
309 | 309 |
310 void indexSet$slow(var a, var index, var value) { | 310 void indexSet$slow(var a, var index, var value) { |
311 if (isJsArray(a)) { | 311 if (isJsArray(a)) { |
312 if (index is !int) { | 312 if (index is !int) { |
313 throw new ArgumentError(index); | 313 throw new ArgumentError(index); |
314 } | 314 } |
315 if (index < 0 || index >= a.length) { | 315 if (index < 0 || index >= a.length) { |
316 throw new RangeError.value(index); | 316 throw new RangeError.value(index); |
317 } | 317 } |
318 checkMutable(a, 'indexed set'); | 318 checkMutable(a, 'indexed set'); |
319 JS('Object', r'#[#] = #', a, index, value); | 319 JS('void', r'#[#] = #', a, index, value); |
320 return; | 320 return; |
321 } | 321 } |
322 UNINTERCEPTED(a[index] = value); | 322 UNINTERCEPTED(a[index] = value); |
323 } | 323 } |
324 | 324 |
325 checkMutable(list, reason) { | 325 checkMutable(list, reason) { |
326 if (JS('bool', r'!!(#.immutable$list)', list)) { | 326 if (JS('bool', r'!!(#.immutable$list)', list)) { |
327 throw new UnsupportedError(reason); | 327 throw new UnsupportedError(reason); |
328 } | 328 } |
329 } | 329 } |
(...skipping 10 matching lines...) Expand all Loading... |
340 return res; | 340 return res; |
341 } | 341 } |
342 | 342 |
343 class ListIterator<T> implements Iterator<T> { | 343 class ListIterator<T> implements Iterator<T> { |
344 int i; | 344 int i; |
345 List<T> list; | 345 List<T> list; |
346 ListIterator(List<T> this.list) : i = 0; | 346 ListIterator(List<T> this.list) : i = 0; |
347 bool get hasNext => i < JS('int', r'#.length', list); | 347 bool get hasNext => i < JS('int', r'#.length', list); |
348 T next() { | 348 T next() { |
349 if (!hasNext) throw new StateError("No more elements"); | 349 if (!hasNext) throw new StateError("No more elements"); |
350 var value = JS('Object', r'#[#]', list, i); | 350 var value = JS('', r'#[#]', list, i); |
351 i += 1; | 351 i += 1; |
352 return value; | 352 return value; |
353 } | 353 } |
354 } | 354 } |
355 | 355 |
356 createInvocationMirror(name, internalName, type, arguments, argumentNames) => | 356 createInvocationMirror(name, internalName, type, arguments, argumentNames) => |
357 new JSInvocationMirror(name, internalName, type, arguments, argumentNames); | 357 new JSInvocationMirror(name, internalName, type, arguments, argumentNames); |
358 | 358 |
359 class JSInvocationMirror implements InvocationMirror { | 359 class JSInvocationMirror implements InvocationMirror { |
360 static const METHOD = 0; | 360 static const METHOD = 0; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 457 } |
458 | 458 |
459 // This is somewhat nasty, but we don't want to drag in a bunch of | 459 // This is somewhat nasty, but we don't want to drag in a bunch of |
460 // dependencies to handle a situation that cannot happen. So we | 460 // dependencies to handle a situation that cannot happen. So we |
461 // avoid using Dart [:throw:] and Dart [toString]. | 461 // avoid using Dart [:throw:] and Dart [toString]. |
462 JS('void', "throw 'Unable to print message: ' + String(#)", string); | 462 JS('void', "throw 'Unable to print message: ' + String(#)", string); |
463 } | 463 } |
464 | 464 |
465 static int parseInt(String string) { | 465 static int parseInt(String string) { |
466 checkString(string); | 466 checkString(string); |
467 var match = JS('List', | 467 var match = JS('=List', |
468 r'/^\s*[+-]?(?:0(x)[a-f0-9]+|\d+)\s*$/i.exec(#)', | 468 r'/^\s*[+-]?(?:0(x)[a-f0-9]+|\d+)\s*$/i.exec(#)', |
469 string); | 469 string); |
470 if (match == null) { | 470 if (match == null) { |
471 throw new FormatException(string); | 471 throw new FormatException(string); |
472 } | 472 } |
473 var base = 10; | 473 var base = 10; |
474 if (match[1] != null) base = 16; | 474 if (match[1] != null) base = 16; |
475 var result = JS('num', r'parseInt(#, #)', string, base); | 475 var result = JS('num', r'parseInt(#, #)', string, base); |
476 if (result.isNaN) throw new FormatException(string); | 476 if (result.isNaN) throw new FormatException(string); |
477 return result; | 477 return result; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(
1); | 515 if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(
1); |
516 return name; | 516 return name; |
517 } | 517 } |
518 | 518 |
519 static String objectToString(Object object) { | 519 static String objectToString(Object object) { |
520 String name = objectTypeName(object); | 520 String name = objectTypeName(object); |
521 return "Instance of '$name'"; | 521 return "Instance of '$name'"; |
522 } | 522 } |
523 | 523 |
524 static List newList(length) { | 524 static List newList(length) { |
525 if (length == null) return JS('Object', r'new Array()'); | 525 // TODO(sra): For good concrete type analysis we need the JS-type to |
| 526 // specifically name the JavaScript Array implementation. 'List' matches |
| 527 // all the dart:html types that implement List<T>. |
| 528 if (length == null) return JS('=List', r'new Array()'); |
526 if ((length is !int) || (length < 0)) { | 529 if ((length is !int) || (length < 0)) { |
527 throw new ArgumentError(length); | 530 throw new ArgumentError(length); |
528 } | 531 } |
529 var result = JS('Object', r'new Array(#)', length); | 532 var result = JS('=List', r'new Array(#)', length); |
530 JS('void', r'#.fixed$length = #', result, true); | 533 JS('void', r'#.fixed$length = #', result, true); |
531 return result; | 534 return result; |
532 } | 535 } |
533 | 536 |
534 static num dateNow() => JS('num', r'Date.now()'); | 537 static num dateNow() => JS('num', r'Date.now()'); |
535 | 538 |
536 static String stringFromCharCodes(charCodes) { | 539 static String stringFromCharCodes(charCodes) { |
537 for (var i in charCodes) { | 540 for (var i in charCodes) { |
538 if (i is !int) throw new ArgumentError(i); | 541 if (i is !int) throw new ArgumentError(i); |
539 } | 542 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 if (value.isNaN || | 579 if (value.isNaN || |
577 value < -MAX_MILLISECONDS_SINCE_EPOCH || | 580 value < -MAX_MILLISECONDS_SINCE_EPOCH || |
578 value > MAX_MILLISECONDS_SINCE_EPOCH) { | 581 value > MAX_MILLISECONDS_SINCE_EPOCH) { |
579 throw new ArgumentError(); | 582 throw new ArgumentError(); |
580 } | 583 } |
581 if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); | 584 if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); |
582 return value; | 585 return value; |
583 } | 586 } |
584 | 587 |
585 static patchUpY2K(value, years, isUtc) { | 588 static patchUpY2K(value, years, isUtc) { |
586 var date = JS('Object', r'new Date(#)', value); | 589 var date = JS('', r'new Date(#)', value); |
587 if (isUtc) { | 590 if (isUtc) { |
588 JS('num', r'#.setUTCFullYear(#)', date, years); | 591 JS('num', r'#.setUTCFullYear(#)', date, years); |
589 } else { | 592 } else { |
590 JS('num', r'#.setFullYear(#)', date, years); | 593 JS('num', r'#.setFullYear(#)', date, years); |
591 } | 594 } |
592 return JS('num', r'#.valueOf()', date); | 595 return JS('num', r'#.valueOf()', date); |
593 } | 596 } |
594 | 597 |
595 // Lazily keep a JS Date stored in the JS object. | 598 // Lazily keep a JS Date stored in the JS object. |
596 static lazyAsJsDate(receiver) { | 599 static lazyAsJsDate(receiver) { |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
888 | 891 |
889 /** | 892 /** |
890 * Throws the given Dart object as an exception by wrapping it in a | 893 * Throws the given Dart object as an exception by wrapping it in a |
891 * proper JavaScript error object and then throwing that. That gives | 894 * proper JavaScript error object and then throwing that. That gives |
892 * us a reasonable stack trace on most JavaScript implementations. The | 895 * us a reasonable stack trace on most JavaScript implementations. The |
893 * code in [unwrapException] deals with getting the original Dart | 896 * code in [unwrapException] deals with getting the original Dart |
894 * object out of the wrapper again. | 897 * object out of the wrapper again. |
895 */ | 898 */ |
896 $throw(ex) { | 899 $throw(ex) { |
897 if (ex == null) ex = const NullPointerException(); | 900 if (ex == null) ex = const NullPointerException(); |
898 var jsError = JS('Object', r'new Error()'); | 901 var jsError = JS('var', r'new Error()'); |
899 JS('void', r'#.name = #', jsError, ex); | 902 JS('void', r'#.name = #', jsError, ex); |
900 JS('void', r'#.description = #', jsError, ex); | 903 JS('void', r'#.description = #', jsError, ex); |
901 JS('void', r'#.dartException = #', jsError, ex); | 904 JS('void', r'#.dartException = #', jsError, ex); |
902 JS('void', r'#.toString = #', jsError, | 905 JS('void', r'#.toString = #', jsError, |
903 DART_CLOSURE_TO_JS(toStringWrapper)); | 906 DART_CLOSURE_TO_JS(toStringWrapper)); |
904 JS('void', r'throw #', jsError); | 907 JS('void', r'throw #', jsError); |
905 } | 908 } |
906 | 909 |
907 /** | 910 /** |
908 * This method is installed as JavaScript toString method on exception | 911 * This method is installed as JavaScript toString method on exception |
909 * objects in [$throw]. So JavaScript 'this' binds to an instance of | 912 * objects in [$throw]. So JavaScript 'this' binds to an instance of |
910 * JavaScript Error to which we have added a property 'dartException' | 913 * JavaScript Error to which we have added a property 'dartException' |
911 * which holds a Dart object. | 914 * which holds a Dart object. |
912 */ | 915 */ |
913 toStringWrapper() => JS('Object', r'this.dartException').toString(); | 916 toStringWrapper() => JS('', r'this.dartException').toString(); |
914 | 917 |
915 makeLiteralListConst(list) { | 918 makeLiteralListConst(list) { |
916 JS('bool', r'#.immutable$list = #', list, true); | 919 JS('bool', r'#.immutable$list = #', list, true); |
917 JS('bool', r'#.fixed$length = #', list, true); | 920 JS('bool', r'#.fixed$length = #', list, true); |
918 return list; | 921 return list; |
919 } | 922 } |
920 | 923 |
921 throwRuntimeError(message) { | 924 throwRuntimeError(message) { |
922 throw new RuntimeError(message); | 925 throw new RuntimeError(message); |
923 } | 926 } |
924 | 927 |
925 throwAbstractClassInstantiationError(className) { | 928 throwAbstractClassInstantiationError(className) { |
926 throw new AbstractClassInstantiationError(className); | 929 throw new AbstractClassInstantiationError(className); |
927 } | 930 } |
928 | 931 |
929 /** | 932 /** |
930 * Called from catch blocks in generated code to extract the Dart | 933 * Called from catch blocks in generated code to extract the Dart |
931 * exception from the thrown value. The thrown value may have been | 934 * exception from the thrown value. The thrown value may have been |
932 * created by [$throw] or it may be a 'native' JS exception. | 935 * created by [$throw] or it may be a 'native' JS exception. |
933 * | 936 * |
934 * Some native exceptions are mapped to new Dart instances, others are | 937 * Some native exceptions are mapped to new Dart instances, others are |
935 * returned unmodified. | 938 * returned unmodified. |
936 */ | 939 */ |
937 unwrapException(ex) { | 940 unwrapException(ex) { |
938 // Note that we are checking if the object has the property. If it | 941 // Note that we are checking if the object has the property. If it |
939 // has, it could be set to null if the thrown value is null. | 942 // has, it could be set to null if the thrown value is null. |
940 if (JS('bool', r'"dartException" in #', ex)) { | 943 if (JS('bool', r'"dartException" in #', ex)) { |
941 return JS('Object', r'#.dartException', ex); | 944 return JS('', r'#.dartException', ex); |
942 } | 945 } |
943 | 946 |
944 // Grab hold of the exception message. This field is available on | 947 // Grab hold of the exception message. This field is available on |
945 // all supported browsers. | 948 // all supported browsers. |
946 var message = JS('var', r'#.message', ex); | 949 var message = JS('var', r'#.message', ex); |
947 | 950 |
948 if (JS('bool', r'# instanceof TypeError', ex)) { | 951 if (JS('bool', r'# instanceof TypeError', ex)) { |
949 // The type and arguments fields are Chrome specific but they | 952 // The type and arguments fields are Chrome specific but they |
950 // allow us to get very detailed information about what kind of | 953 // allow us to get very detailed information about what kind of |
951 // exception occurred. | 954 // exception occurred. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 */ | 1106 */ |
1104 getFallThroughError() => const FallThroughErrorImplementation(); | 1107 getFallThroughError() => const FallThroughErrorImplementation(); |
1105 | 1108 |
1106 /** | 1109 /** |
1107 * Represents the type Dynamic. The compiler treats this specially. | 1110 * Represents the type Dynamic. The compiler treats this specially. |
1108 */ | 1111 */ |
1109 abstract class Dynamic_ { | 1112 abstract class Dynamic_ { |
1110 } | 1113 } |
1111 | 1114 |
1112 /** | 1115 /** |
| 1116 * A metadata annotation describing the types instantiated by a native element. |
| 1117 */ |
| 1118 class Creates { |
| 1119 final String types; |
| 1120 const Creates(this.types); |
| 1121 } |
| 1122 |
| 1123 /** |
| 1124 * A metadata annotation describing the types returned or yielded by a native |
| 1125 * element. |
| 1126 */ |
| 1127 class Returns { |
| 1128 final String types; |
| 1129 const Returns(this.types); |
| 1130 } |
| 1131 |
| 1132 /** |
1113 * Represents the type of Null. The compiler treats this specially. | 1133 * Represents the type of Null. The compiler treats this specially. |
1114 * TODO(lrn): Null should be defined in core. It's a class, like int. | 1134 * TODO(lrn): Null should be defined in core. It's a class, like int. |
1115 * It just happens to act differently in assignability tests and, | 1135 * It just happens to act differently in assignability tests and, |
1116 * like int, can't be extended or implemented. | 1136 * like int, can't be extended or implemented. |
1117 */ | 1137 */ |
1118 class Null { | 1138 class Null { |
1119 factory Null() { | 1139 factory Null() { |
1120 throw new UnsupportedError('new Null()'); | 1140 throw new UnsupportedError('new Null()'); |
1121 } | 1141 } |
1122 } | 1142 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 Type getOrCreateCachedRuntimeType(String key) { | 1493 Type getOrCreateCachedRuntimeType(String key) { |
1474 Type result = JS('Type', r'#[#]', runtimeTypeCache, key); | 1494 Type result = JS('Type', r'#[#]', runtimeTypeCache, key); |
1475 if (result == null) { | 1495 if (result == null) { |
1476 result = new TypeImpl(key); | 1496 result = new TypeImpl(key); |
1477 JS('var', r'#[#] = #', runtimeTypeCache, key, result); | 1497 JS('var', r'#[#] = #', runtimeTypeCache, key, result); |
1478 } | 1498 } |
1479 return result; | 1499 return result; |
1480 } | 1500 } |
1481 | 1501 |
1482 String getRuntimeTypeString(var object) { | 1502 String getRuntimeTypeString(var object) { |
1483 var typeInfo = JS('Object', r'#.builtin$typeInfo', object); | 1503 var typeInfo = JS('var', r'#.builtin$typeInfo', object); |
1484 return JS('String', r'#.runtimeType', typeInfo); | 1504 return JS('String', r'#.runtimeType', typeInfo); |
1485 } | 1505 } |
OLD | NEW |