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('coreimpl.dart'); | 7 #import('coreimpl.dart'); |
8 | 8 |
9 #source('constant_map.dart'); | 9 #source('constant_map.dart'); |
10 #source('native_helper.dart'); | 10 #source('native_helper.dart'); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 return; | 90 return; |
91 } | 91 } |
92 } | 92 } |
93 indexSet$slow(a, index, value); | 93 indexSet$slow(a, index, value); |
94 } | 94 } |
95 | 95 |
96 /** | 96 /** |
97 * Returns true if both arguments are numbers. | 97 * Returns true if both arguments are numbers. |
98 * | 98 * |
99 * If only the first argument is a number, an | 99 * If only the first argument is a number, an |
100 * [IllegalArgumentException] with the other argument is thrown. | 100 * [ArgumentError] with the other argument is thrown. |
101 */ | 101 */ |
102 bool checkNumbers(var a, var b) { | 102 bool checkNumbers(var a, var b) { |
103 if (a is num) { | 103 if (a is num) { |
104 if (b is num) { | 104 if (b is num) { |
105 return true; | 105 return true; |
106 } else { | 106 } else { |
107 checkNull(b); | 107 checkNull(b); |
108 throw new IllegalArgumentException(b); | 108 throw new ArgumentError(b); |
109 } | 109 } |
110 } | 110 } |
111 return false; | 111 return false; |
112 } | 112 } |
113 | 113 |
114 bool isJsArray(var value) { | 114 bool isJsArray(var value) { |
115 return value !== null && JS('bool', r'#.constructor === Array', value); | 115 return value !== null && JS('bool', r'#.constructor === Array', value); |
116 } | 116 } |
117 | 117 |
118 add$slow(var a, var b) { | 118 add$slow(var a, var b) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 le$slow(var a, var b) { | 217 le$slow(var a, var b) { |
218 if (checkNumbers(a, b)) { | 218 if (checkNumbers(a, b)) { |
219 return JS('bool', r'# <= #', a, b); | 219 return JS('bool', r'# <= #', a, b); |
220 } | 220 } |
221 return UNINTERCEPTED(a <= b); | 221 return UNINTERCEPTED(a <= b); |
222 } | 222 } |
223 | 223 |
224 shl(var a, var b) { | 224 shl(var a, var b) { |
225 // TODO(floitsch): inputs must be integers. | 225 // TODO(floitsch): inputs must be integers. |
226 if (checkNumbers(a, b)) { | 226 if (checkNumbers(a, b)) { |
227 if (JS('num', '#', b) < 0) throw new IllegalArgumentException(b); | 227 if (JS('num', '#', b) < 0) throw new ArgumentError(b); |
228 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting | 228 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting |
229 // by 33 is hence equivalent to a shift by 1. | 229 // by 33 is hence equivalent to a shift by 1. |
230 if (JS('bool', r'# > 31', b)) return 0; | 230 if (JS('bool', r'# > 31', b)) return 0; |
231 return JS('num', r'(# << #) >>> 0', a, b); | 231 return JS('num', r'(# << #) >>> 0', a, b); |
232 } | 232 } |
233 return UNINTERCEPTED(a << b); | 233 return UNINTERCEPTED(a << b); |
234 } | 234 } |
235 | 235 |
236 shr(var a, var b) { | 236 shr(var a, var b) { |
237 // TODO(floitsch): inputs must be integers. | 237 // TODO(floitsch): inputs must be integers. |
238 if (checkNumbers(a, b)) { | 238 if (checkNumbers(a, b)) { |
239 if (JS('num', '#', b) < 0) throw new IllegalArgumentException(b); | 239 if (JS('num', '#', b) < 0) throw new ArgumentError(b); |
240 if (JS('num', '#', a) > 0) { | 240 if (JS('num', '#', a) > 0) { |
241 // JavaScript only looks at the last 5 bits of the shift-amount. In JS | 241 // JavaScript only looks at the last 5 bits of the shift-amount. In JS |
242 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the | 242 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the |
243 // computation when that happens. | 243 // computation when that happens. |
244 if (JS('bool', r'# > 31', b)) return 0; | 244 if (JS('bool', r'# > 31', b)) return 0; |
245 // Given that 'a' is positive we must not use '>>'. Otherwise a number | 245 // Given that 'a' is positive we must not use '>>'. Otherwise a number |
246 // that has the 31st bit set would be treated as negative and shift in | 246 // that has the 31st bit set would be treated as negative and shift in |
247 // ones. | 247 // ones. |
248 return JS('num', r'# >>> #', a, b); | 248 return JS('num', r'# >>> #', a, b); |
249 } | 249 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 288 } |
289 | 289 |
290 neg(var a) { | 290 neg(var a) { |
291 if (JS('bool', r'typeof # === "number"', a)) return JS('num', r'-#', a); | 291 if (JS('bool', r'typeof # === "number"', a)) return JS('num', r'-#', a); |
292 return UNINTERCEPTED(-a); | 292 return UNINTERCEPTED(-a); |
293 } | 293 } |
294 | 294 |
295 index$slow(var a, var index) { | 295 index$slow(var a, var index) { |
296 if (a is String || isJsArray(a)) { | 296 if (a is String || isJsArray(a)) { |
297 if (index is !int) { | 297 if (index is !int) { |
298 if (index is !num) throw new IllegalArgumentException(index); | 298 if (index is !num) throw new ArgumentError(index); |
299 if (index.truncate() !== index) throw new IllegalArgumentException(index); | 299 if (index.truncate() !== index) throw new ArgumentError(index); |
300 } | 300 } |
301 if (index < 0 || index >= a.length) { | 301 if (index < 0 || index >= a.length) { |
302 throw new IndexOutOfRangeException(index); | 302 throw new IndexOutOfRangeException(index); |
303 } | 303 } |
304 return JS('Object', r'#[#]', a, index); | 304 return JS('Object', r'#[#]', a, index); |
305 } | 305 } |
306 return UNINTERCEPTED(a[index]); | 306 return UNINTERCEPTED(a[index]); |
307 } | 307 } |
308 | 308 |
309 void indexSet$slow(var a, var index, var value) { | 309 void indexSet$slow(var a, var index, var value) { |
310 if (isJsArray(a)) { | 310 if (isJsArray(a)) { |
311 if (index is !int) { | 311 if (index is !int) { |
312 throw new IllegalArgumentException(index); | 312 throw new ArgumentError(index); |
313 } | 313 } |
314 if (index < 0 || index >= a.length) { | 314 if (index < 0 || index >= a.length) { |
315 throw new IndexOutOfRangeException(index); | 315 throw new IndexOutOfRangeException(index); |
316 } | 316 } |
317 checkMutable(a, 'indexed set'); | 317 checkMutable(a, 'indexed set'); |
318 JS('Object', r'#[#] = #', a, index, value); | 318 JS('Object', r'#[#] = #', a, index, value); |
319 return; | 319 return; |
320 } | 320 } |
321 UNINTERCEPTED(a[index] = value); | 321 UNINTERCEPTED(a[index] = value); |
322 } | 322 } |
323 | 323 |
324 checkMutable(list, reason) { | 324 checkMutable(list, reason) { |
325 if (JS('bool', r'!!(#.immutable$list)', list)) { | 325 if (JS('bool', r'!!(#.immutable$list)', list)) { |
326 throw new UnsupportedOperationException(reason); | 326 throw new UnsupportedOperationException(reason); |
327 } | 327 } |
328 } | 328 } |
329 | 329 |
330 checkGrowable(list, reason) { | 330 checkGrowable(list, reason) { |
331 if (JS('bool', r'!!(#.fixed$length)', list)) { | 331 if (JS('bool', r'!!(#.fixed$length)', list)) { |
332 throw new UnsupportedOperationException(reason); | 332 throw new UnsupportedOperationException(reason); |
333 } | 333 } |
334 } | 334 } |
335 | 335 |
336 String S(value) { | 336 String S(value) { |
337 var res = value.toString(); | 337 var res = value.toString(); |
338 if (res is !String) throw new IllegalArgumentException(value); | 338 if (res is !String) throw new ArgumentError(value); |
339 return res; | 339 return res; |
340 } | 340 } |
341 | 341 |
342 class ListIterator<T> implements Iterator<T> { | 342 class ListIterator<T> implements Iterator<T> { |
343 int i; | 343 int i; |
344 List<T> list; | 344 List<T> list; |
345 ListIterator(List<T> this.list) : i = 0; | 345 ListIterator(List<T> this.list) : i = 0; |
346 bool hasNext() => i < JS('int', r'#.length', list); | 346 bool hasNext() => i < JS('int', r'#.length', list); |
347 T next() { | 347 T next() { |
348 if (!hasNext()) throw new NoMoreElementsException(); | 348 if (!hasNext()) throw new NoMoreElementsException(); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 } | 445 } |
446 | 446 |
447 static String objectToString(Object object) { | 447 static String objectToString(Object object) { |
448 String name = objectTypeName(object); | 448 String name = objectTypeName(object); |
449 return "Instance of '$name'"; | 449 return "Instance of '$name'"; |
450 } | 450 } |
451 | 451 |
452 static List newList(length) { | 452 static List newList(length) { |
453 if (length === null) return JS('Object', r'new Array()'); | 453 if (length === null) return JS('Object', r'new Array()'); |
454 if ((length is !int) || (length < 0)) { | 454 if ((length is !int) || (length < 0)) { |
455 throw new IllegalArgumentException(length); | 455 throw new ArgumentError(length); |
456 } | 456 } |
457 var result = JS('Object', r'new Array(#)', length); | 457 var result = JS('Object', r'new Array(#)', length); |
458 JS('void', r'#.fixed$length = #', result, true); | 458 JS('void', r'#.fixed$length = #', result, true); |
459 return result; | 459 return result; |
460 } | 460 } |
461 | 461 |
462 static num dateNow() => JS('num', r'Date.now()'); | 462 static num dateNow() => JS('num', r'Date.now()'); |
463 | 463 |
464 static String stringFromCharCodes(charCodes) { | 464 static String stringFromCharCodes(charCodes) { |
465 for (var i in charCodes) { | 465 for (var i in charCodes) { |
466 if (i is !int) throw new IllegalArgumentException(i); | 466 if (i is !int) throw new ArgumentError(i); |
467 } | 467 } |
468 return JS('String', r'String.fromCharCode.apply(#, #)', null, charCodes); | 468 return JS('String', r'String.fromCharCode.apply(#, #)', null, charCodes); |
469 } | 469 } |
470 | 470 |
471 static String getTimeZoneName(receiver) { | 471 static String getTimeZoneName(receiver) { |
472 // When calling toString on a Date it will emit the timezone in parenthesis. | 472 // When calling toString on a Date it will emit the timezone in parenthesis. |
473 // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)". | 473 // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)". |
474 // We extract this name using a regexp. | 474 // We extract this name using a regexp. |
475 var d = lazyAsJsDate(receiver); | 475 var d = lazyAsJsDate(receiver); |
476 return JS('String', r'/\((.*)\)/.exec(#.toString())[1]', d); | 476 return JS('String', r'/\((.*)\)/.exec(#.toString())[1]', d); |
(...skipping 20 matching lines...) Expand all Loading... |
497 if (isUtc) { | 497 if (isUtc) { |
498 value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', | 498 value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', |
499 years, jsMonth, day, hours, minutes, seconds, milliseconds); | 499 years, jsMonth, day, hours, minutes, seconds, milliseconds); |
500 } else { | 500 } else { |
501 value = JS('num', r'new Date(#, #, #, #, #, #, #).valueOf()', | 501 value = JS('num', r'new Date(#, #, #, #, #, #, #).valueOf()', |
502 years, jsMonth, day, hours, minutes, seconds, milliseconds); | 502 years, jsMonth, day, hours, minutes, seconds, milliseconds); |
503 } | 503 } |
504 if (value.isNaN() || | 504 if (value.isNaN() || |
505 value < -MAX_MILLISECONDS_SINCE_EPOCH || | 505 value < -MAX_MILLISECONDS_SINCE_EPOCH || |
506 value > MAX_MILLISECONDS_SINCE_EPOCH) { | 506 value > MAX_MILLISECONDS_SINCE_EPOCH) { |
507 throw new IllegalArgumentException(); | 507 throw new ArgumentError(); |
508 } | 508 } |
509 if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); | 509 if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); |
510 return value; | 510 return value; |
511 } | 511 } |
512 | 512 |
513 static patchUpY2K(value, years, isUtc) { | 513 static patchUpY2K(value, years, isUtc) { |
514 var date = JS('Object', r'new Date(#)', value); | 514 var date = JS('Object', r'new Date(#)', value); |
515 if (isUtc) { | 515 if (isUtc) { |
516 JS('num', r'#.setUTCFullYear(#)', date, years); | 516 JS('num', r'#.setUTCFullYear(#)', date, years); |
517 } else { | 517 } else { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 static getWeekday(receiver) { | 574 static getWeekday(receiver) { |
575 int weekday = (receiver.isUtc) | 575 int weekday = (receiver.isUtc) |
576 ? JS('int', r'#.getUTCDay()', lazyAsJsDate(receiver)) | 576 ? JS('int', r'#.getUTCDay()', lazyAsJsDate(receiver)) |
577 : JS('int', r'#.getDay()', lazyAsJsDate(receiver)); | 577 : JS('int', r'#.getDay()', lazyAsJsDate(receiver)); |
578 // Adjust by one because JS weeks start on Sunday. | 578 // Adjust by one because JS weeks start on Sunday. |
579 return (weekday + 6) % 7 + 1; | 579 return (weekday + 6) % 7 + 1; |
580 } | 580 } |
581 | 581 |
582 static valueFromDateString(str) { | 582 static valueFromDateString(str) { |
583 checkNull(str); | 583 checkNull(str); |
584 if (str is !String) throw new IllegalArgumentException(str); | 584 if (str is !String) throw new ArgumentError(str); |
585 var value = JS('num', r'Date.parse(#)', str); | 585 var value = JS('num', r'Date.parse(#)', str); |
586 if (value.isNaN()) throw new IllegalArgumentException(str); | 586 if (value.isNaN()) throw new ArgumentError(str); |
587 return value; | 587 return value; |
588 } | 588 } |
589 | 589 |
590 static getProperty(object, key) { | 590 static getProperty(object, key) { |
591 checkNull(object); | 591 checkNull(object); |
592 if (object is bool || object is num || object is String) { | 592 if (object is bool || object is num || object is String) { |
593 throw new IllegalArgumentException(object); | 593 throw new ArgumentError(object); |
594 } | 594 } |
595 return JS('var', '#[#]', object, key); | 595 return JS('var', '#[#]', object, key); |
596 } | 596 } |
597 | 597 |
598 static void setProperty(object, key, value) { | 598 static void setProperty(object, key, value) { |
599 checkNull(object); | 599 checkNull(object); |
600 if (object is bool || object is num || object is String) { | 600 if (object is bool || object is num || object is String) { |
601 throw new IllegalArgumentException(object); | 601 throw new ArgumentError(object); |
602 } | 602 } |
603 JS('void', '#[#] = #', object, key, value); | 603 JS('void', '#[#] = #', object, key, value); |
604 } | 604 } |
605 } | 605 } |
606 | 606 |
607 /** | 607 /** |
608 * Called by generated code to throw an illegal-argument exception, | 608 * Called by generated code to throw an illegal-argument exception, |
609 * for example, if a non-integer index is given to an optimized | 609 * for example, if a non-integer index is given to an optimized |
610 * indexed access. | 610 * indexed access. |
611 */ | 611 */ |
612 iae(argument) { | 612 iae(argument) { |
613 throw new IllegalArgumentException(argument); | 613 throw new ArgumentError(argument); |
614 } | 614 } |
615 | 615 |
616 /** | 616 /** |
617 * Called by generated code to throw an index-out-of-range exception, | 617 * Called by generated code to throw an index-out-of-range exception, |
618 * for example, if a bounds check fails in an optimized indexed | 618 * for example, if a bounds check fails in an optimized indexed |
619 * access. | 619 * access. |
620 */ | 620 */ |
621 ioore(index) { | 621 ioore(index) { |
622 throw new IndexOutOfRangeException(index); | 622 throw new IndexOutOfRangeException(index); |
623 } | 623 } |
624 | 624 |
625 listInsertRange(receiver, start, length, initialValue) { | 625 listInsertRange(receiver, start, length, initialValue) { |
626 if (length === 0) { | 626 if (length === 0) { |
627 return; | 627 return; |
628 } | 628 } |
629 checkNull(start); // TODO(ahe): This is not specified but co19 tests it. | 629 checkNull(start); // TODO(ahe): This is not specified but co19 tests it. |
630 checkNull(length); // TODO(ahe): This is not specified but co19 tests it. | 630 checkNull(length); // TODO(ahe): This is not specified but co19 tests it. |
631 if (length is !int) throw new IllegalArgumentException(length); | 631 if (length is !int) throw new ArgumentError(length); |
632 if (length < 0) throw new IllegalArgumentException(length); | 632 if (length < 0) throw new ArgumentError(length); |
633 if (start is !int) throw new IllegalArgumentException(start); | 633 if (start is !int) throw new ArgumentError(start); |
634 | 634 |
635 var receiverLength = JS('num', r'#.length', receiver); | 635 var receiverLength = JS('num', r'#.length', receiver); |
636 if (start < 0 || start > receiverLength) { | 636 if (start < 0 || start > receiverLength) { |
637 throw new IndexOutOfRangeException(start); | 637 throw new IndexOutOfRangeException(start); |
638 } | 638 } |
639 receiver.length = receiverLength + length; | 639 receiver.length = receiverLength + length; |
640 Arrays.copy(receiver, | 640 Arrays.copy(receiver, |
641 start, | 641 start, |
642 receiver, | 642 receiver, |
643 start + length, | 643 start + length, |
(...skipping 11 matching lines...) Expand all Loading... |
655 | 655 |
656 | 656 |
657 checkNull(object) { | 657 checkNull(object) { |
658 if (object === null) throw new NullPointerException(); | 658 if (object === null) throw new NullPointerException(); |
659 return object; | 659 return object; |
660 } | 660 } |
661 | 661 |
662 checkNum(value) { | 662 checkNum(value) { |
663 if (value is !num) { | 663 if (value is !num) { |
664 checkNull(value); | 664 checkNull(value); |
665 throw new IllegalArgumentException(value); | 665 throw new ArgumentError(value); |
666 } | 666 } |
667 return value; | 667 return value; |
668 } | 668 } |
669 | 669 |
670 checkInt(value) { | 670 checkInt(value) { |
671 if (value is !int) { | 671 if (value is !int) { |
672 checkNull(value); | 672 checkNull(value); |
673 throw new IllegalArgumentException(value); | 673 throw new ArgumentError(value); |
674 } | 674 } |
675 return value; | 675 return value; |
676 } | 676 } |
677 | 677 |
678 checkBool(value) { | 678 checkBool(value) { |
679 if (value is !bool) { | 679 if (value is !bool) { |
680 checkNull(value); | 680 checkNull(value); |
681 throw new IllegalArgumentException(value); | 681 throw new ArgumentError(value); |
682 } | 682 } |
683 return value; | 683 return value; |
684 } | 684 } |
685 | 685 |
686 checkString(value) { | 686 checkString(value) { |
687 if (value is !String) { | 687 if (value is !String) { |
688 checkNull(value); | 688 checkNull(value); |
689 throw new IllegalArgumentException(value); | 689 throw new ArgumentError(value); |
690 } | 690 } |
691 return value; | 691 return value; |
692 } | 692 } |
693 | 693 |
694 substringUnchecked(receiver, startIndex, endIndex) | 694 substringUnchecked(receiver, startIndex, endIndex) |
695 => JS('String', r'#.substring(#, #)', receiver, startIndex, endIndex); | 695 => JS('String', r'#.substring(#, #)', receiver, startIndex, endIndex); |
696 | 696 |
697 class MathNatives { | 697 class MathNatives { |
698 static int parseInt(str) { | 698 static int parseInt(str) { |
699 checkString(str); | 699 checkString(str); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 } | 872 } |
873 | 873 |
874 if (JS('bool', r'# instanceof RangeError', ex)) { | 874 if (JS('bool', r'# instanceof RangeError', ex)) { |
875 if (message is String && message.contains('call stack')) { | 875 if (message is String && message.contains('call stack')) { |
876 return new StackOverflowException(); | 876 return new StackOverflowException(); |
877 } | 877 } |
878 | 878 |
879 // In general, a RangeError is thrown when trying to pass a number | 879 // In general, a RangeError is thrown when trying to pass a number |
880 // as an argument to a function that does not allow a range that | 880 // as an argument to a function that does not allow a range that |
881 // includes that number. | 881 // includes that number. |
882 return new IllegalArgumentException(); | 882 return new ArgumentError(); |
883 } | 883 } |
884 | 884 |
885 // Check for the Firefox specific stack overflow signal. | 885 // Check for the Firefox specific stack overflow signal. |
886 if (JS('bool', | 886 if (JS('bool', |
887 r"typeof InternalError == 'function' && # instanceof InternalError", | 887 r"typeof InternalError == 'function' && # instanceof InternalError", |
888 ex)) { | 888 ex)) { |
889 if (message is String && message == 'too much recursion') { | 889 if (message is String && message == 'too much recursion') { |
890 return new StackOverflowException(); | 890 return new StackOverflowException(); |
891 } | 891 } |
892 } | 892 } |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 JS('void', r'#.runtimeTypeCache[#] = #', JS_CURRENT_ISOLATE(), key, | 1353 JS('void', r'#.runtimeTypeCache[#] = #', JS_CURRENT_ISOLATE(), key, |
1354 runtimeType); | 1354 runtimeType); |
1355 } | 1355 } |
1356 return runtimeType; | 1356 return runtimeType; |
1357 } | 1357 } |
1358 | 1358 |
1359 String getRuntimeTypeString(var object) { | 1359 String getRuntimeTypeString(var object) { |
1360 var typeInfo = JS('Object', r'#.builtin$typeInfo', object); | 1360 var typeInfo = JS('Object', r'#.builtin$typeInfo', object); |
1361 return JS('String', r'#.runtimeType', typeInfo); | 1361 return JS('String', r'#.runtimeType', typeInfo); |
1362 } | 1362 } |
OLD | NEW |