| 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 |