OLD | NEW |
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 library _js_helper; | 5 library _js_helper; |
6 | 6 |
7 import 'dart:_async_await_error_codes' as async_error_codes; | 7 import 'dart:_async_await_error_codes' as async_error_codes; |
8 | 8 |
9 import 'dart:_js_embedded_names' show | 9 import 'dart:_js_embedded_names' show |
10 DEFERRED_LIBRARY_URIS, | 10 DEFERRED_LIBRARY_URIS, |
(...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 static void update(cache, String key, value) { | 1381 static void update(cache, String key, value) { |
1382 JS('void', '#[#] = #', cache, key, value); | 1382 JS('void', '#[#] = #', cache, key, value); |
1383 } | 1383 } |
1384 } | 1384 } |
1385 | 1385 |
1386 /** | 1386 /** |
1387 * Called by generated code to throw an illegal-argument exception, | 1387 * Called by generated code to throw an illegal-argument exception, |
1388 * for example, if a non-integer index is given to an optimized | 1388 * for example, if a non-integer index is given to an optimized |
1389 * indexed access. | 1389 * indexed access. |
1390 */ | 1390 */ |
| 1391 @NoInline() |
1391 iae(argument) { | 1392 iae(argument) { |
1392 throw _argumentError(argument); | 1393 throw _argumentError(argument); |
1393 } | 1394 } |
1394 | 1395 |
1395 /** | 1396 /** |
1396 * Called by generated code to throw an index-out-of-range exception, | 1397 * Called by generated code to throw an index-out-of-range exception, for |
1397 * for example, if a bounds check fails in an optimized indexed | 1398 * example, if a bounds check fails in an optimized indexed access. This may |
1398 * access. This may also be called when the index is not an integer, in | 1399 * also be called when the index is not an integer, in which case it throws an |
1399 * which case it throws an illegal-argument exception instead, like | 1400 * illegal-argument exception instead, like [iae], or when the receiver is null. |
1400 * [iae], or when the receiver is null. | |
1401 */ | 1401 */ |
| 1402 @NoInline() |
1402 ioore(receiver, index) { | 1403 ioore(receiver, index) { |
1403 if (receiver == null) receiver.length; // Force a NoSuchMethodError. | 1404 if (receiver == null) receiver.length; // Force a NoSuchMethodError. |
1404 if (index is !int) iae(index); | 1405 throw diagnoseIndexError(receiver, index); |
1405 throw new RangeError.value(index); | |
1406 } | 1406 } |
1407 | 1407 |
| 1408 /** |
| 1409 * Diagnoses an indexing error. Returns the ArgumentError or RangeError that |
| 1410 * describes the problem. |
| 1411 */ |
| 1412 @NoInline() |
| 1413 Error diagnoseIndexError(indexable, index) { |
| 1414 if (index is !int) return new ArgumentError.value(index, 'index'); |
| 1415 int length = indexable.length; |
| 1416 // The following returns the same error that would be thrown by calling |
| 1417 // [RangeError.checkValidIndex] with no optional parameters provided. |
| 1418 if (index < 0 || index >= length) { |
| 1419 return new RangeError.index(index, indexable, 'index', null, length); |
| 1420 } |
| 1421 // The above should always match, but if it does not, use the following. |
| 1422 return new RangeError.value(index, 'index'); |
| 1423 } |
| 1424 |
| 1425 |
1408 stringLastIndexOfUnchecked(receiver, element, start) | 1426 stringLastIndexOfUnchecked(receiver, element, start) |
1409 => JS('int', r'#.lastIndexOf(#, #)', receiver, element, start); | 1427 => JS('int', r'#.lastIndexOf(#, #)', receiver, element, start); |
1410 | 1428 |
1411 | 1429 |
1412 /// 'factory' for constructing ArgumentError.value to keep the call sites small. | 1430 /// 'factory' for constructing ArgumentError.value to keep the call sites small. |
1413 @NoInline() | 1431 @NoInline() |
1414 ArgumentError _argumentError(object) { | 1432 ArgumentError _argumentError(object) { |
1415 return new ArgumentError.value(object); | 1433 return new ArgumentError.value(object); |
1416 } | 1434 } |
1417 | 1435 |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2008 // nothing. | 2026 // nothing. |
2009 return saveStackTrace( | 2027 return saveStackTrace( |
2010 new UnknownJsTypeError(message is String ? message : '')); | 2028 new UnknownJsTypeError(message is String ? message : '')); |
2011 } | 2029 } |
2012 | 2030 |
2013 if (JS('bool', r'# instanceof RangeError', ex)) { | 2031 if (JS('bool', r'# instanceof RangeError', ex)) { |
2014 if (message is String && contains(message, 'call stack')) { | 2032 if (message is String && contains(message, 'call stack')) { |
2015 return new StackOverflowError(); | 2033 return new StackOverflowError(); |
2016 } | 2034 } |
2017 | 2035 |
2018 // In general, a RangeError is thrown when trying to pass a number | 2036 // In general, a RangeError is thrown when trying to pass a number as an |
2019 // as an argument to a function that does not allow a range that | 2037 // argument to a function that does not allow a range that includes that |
2020 // includes that number. | 2038 // number. Translate to a Dart ArgumentError with the same message. |
2021 return saveStackTrace(new ArgumentError()); | 2039 // TODO(sra): Translate to RangeError. |
| 2040 String message = tryStringifyException(ex); |
| 2041 if (message is String) { |
| 2042 message = JS('String', r'#.replace(/^RangeError:\s*/, "")', message); |
| 2043 } |
| 2044 return saveStackTrace(new ArgumentError(message)); |
2022 } | 2045 } |
2023 | 2046 |
2024 // Check for the Firefox specific stack overflow signal. | 2047 // Check for the Firefox specific stack overflow signal. |
2025 if (JS('bool', | 2048 if (JS('bool', |
2026 r'typeof InternalError == "function" && # instanceof InternalError', | 2049 r'typeof InternalError == "function" && # instanceof InternalError', |
2027 ex)) { | 2050 ex)) { |
2028 if (message is String && message == 'too much recursion') { | 2051 if (message is String && message == 'too much recursion') { |
2029 return new StackOverflowError(); | 2052 return new StackOverflowError(); |
2030 } | 2053 } |
2031 } | 2054 } |
2032 | 2055 |
2033 // Just return the exception. We should not wrap it because in case | 2056 // Just return the exception. We should not wrap it because in case |
2034 // the exception comes from the DOM, it is a JavaScript | 2057 // the exception comes from the DOM, it is a JavaScript |
2035 // object backed by a native Dart class. | 2058 // object backed by a native Dart class. |
2036 return ex; | 2059 return ex; |
2037 } | 2060 } |
2038 | 2061 |
| 2062 String tryStringifyException(ex) { |
| 2063 // Since this function is called from [unwrapException] which is called from |
| 2064 // code injected into a catch-clause, use JavaScript try-catch to avoid a |
| 2065 // potential loop if stringifying crashes. |
| 2066 return JS('String|Null', r''' |
| 2067 (function(ex) { |
| 2068 try { |
| 2069 return String(ex); |
| 2070 } catch (e) {} |
| 2071 return null; |
| 2072 })(#) |
| 2073 ''', ex); |
| 2074 } |
| 2075 |
2039 /** | 2076 /** |
2040 * Called by generated code to fetch the stack trace from an | 2077 * Called by generated code to fetch the stack trace from an |
2041 * exception. Should never return null. | 2078 * exception. Should never return null. |
2042 */ | 2079 */ |
2043 StackTrace getTraceFromException(exception) { | 2080 StackTrace getTraceFromException(exception) { |
2044 if (exception is ExceptionAndStackTrace) { | 2081 if (exception is ExceptionAndStackTrace) { |
2045 return exception.stackTrace; | 2082 return exception.stackTrace; |
2046 } | 2083 } |
2047 if (exception == null) return new _StackTrace(exception); | 2084 if (exception == null) return new _StackTrace(exception); |
2048 _StackTrace trace = JS('_StackTrace|Null', r'#.$cachedTrace', exception); | 2085 _StackTrace trace = JS('_StackTrace|Null', r'#.$cachedTrace', exception); |
(...skipping 2043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4092 // This is a function that will return a helper function that does the | 4129 // This is a function that will return a helper function that does the |
4093 // iteration of the sync*. | 4130 // iteration of the sync*. |
4094 // | 4131 // |
4095 // Each invocation should give a body with fresh state. | 4132 // Each invocation should give a body with fresh state. |
4096 final dynamic /* js function */ _outerHelper; | 4133 final dynamic /* js function */ _outerHelper; |
4097 | 4134 |
4098 SyncStarIterable(this._outerHelper); | 4135 SyncStarIterable(this._outerHelper); |
4099 | 4136 |
4100 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); | 4137 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); |
4101 } | 4138 } |
OLD | NEW |