Index: tool/input_sdk/private/native_typed_data.dart |
diff --git a/tool/input_sdk/private/native_typed_data.dart b/tool/input_sdk/private/native_typed_data.dart |
index b9b4343ecd0ab670f577ef7f5c349cdf71d07e83..40c3f767c299131a722dd8830310a20d9aeefa07 100644 |
--- a/tool/input_sdk/private/native_typed_data.dart |
+++ b/tool/input_sdk/private/native_typed_data.dart |
@@ -12,7 +12,8 @@ import 'dart:collection'; |
import 'dart:_internal'; |
import 'dart:_interceptors' show JSIndexable; |
import 'dart:_js_helper' |
-show Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns; |
+show Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns, |
+ diagnoseIndexError, diagnoseRangeError; |
import 'dart:_foreign_helper' show JS; |
import 'dart:math' as Math; |
@@ -147,39 +148,10 @@ class NativeFloat32x4List |
int get elementSizeInBytes => Float32x4List.BYTES_PER_ELEMENT; |
- void _invalidIndex(int index, int length) { |
- if (index < 0 || index >= length) { |
- if (length == this.length) { |
- throw new RangeError.index(index, this); |
- } |
- throw new RangeError.range(index, 0, length - 1); |
- } else { |
- throw new ArgumentError('Invalid list index $index'); |
- } |
- } |
- |
- void _checkIndex(int index, int length) { |
- if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) { |
- _invalidIndex(index, length); |
- } |
- } |
- |
- int _checkSublistArguments(int start, int end, int length) { |
- // For `sublist` the [start] and [end] indices are allowed to be equal to |
- // [length]. However, [_checkIndex] only allows indices in the range |
- // 0 .. length - 1. We therefore increment the [length] argument by one |
- // for the [_checkIndex] checks. |
- _checkIndex(start, length + 1); |
- if (end == null) return length; |
- _checkIndex(end, length + 1); |
- if (start > end) throw new RangeError.range(start, 0, end); |
- return end; |
- } |
- |
int get length => _storage.length ~/ 4; |
Float32x4 operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
double _x = _storage[(index * 4) + 0]; |
double _y = _storage[(index * 4) + 1]; |
double _z = _storage[(index * 4) + 2]; |
@@ -188,7 +160,7 @@ class NativeFloat32x4List |
} |
void operator[]=(int index, Float32x4 value) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
_storage[(index * 4) + 0] = value.x; |
_storage[(index * 4) + 1] = value.y; |
_storage[(index * 4) + 2] = value.z; |
@@ -196,7 +168,7 @@ class NativeFloat32x4List |
} |
List<Float32x4> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
return new NativeFloat32x4List._externalStorage( |
_storage.sublist(start * 4, end * 4)); |
} |
@@ -256,40 +228,10 @@ class NativeInt32x4List |
int get elementSizeInBytes => Int32x4List.BYTES_PER_ELEMENT; |
- void _invalidIndex(int index, int length) { |
- if (index < 0 || index >= length) { |
- if (length == this.length) { |
- throw new RangeError.index(index, this); |
- } |
- throw new RangeError.range(index, 0, length - 1); |
- } else { |
- throw new ArgumentError('Invalid list index $index'); |
- } |
- } |
- |
- void _checkIndex(int index, int length) { |
- if (JS('bool', '(# >>> 0 != #)', index, index) |
- || JS('bool', '# >= #', index, length)) { |
- _invalidIndex(index, length); |
- } |
- } |
- |
- int _checkSublistArguments(int start, int end, int length) { |
- // For `sublist` the [start] and [end] indices are allowed to be equal to |
- // [length]. However, [_checkIndex] only allows indices in the range |
- // 0 .. length - 1. We therefore increment the [length] argument by one |
- // for the [_checkIndex] checks. |
- _checkIndex(start, length + 1); |
- if (end == null) return length; |
- _checkIndex(end, length + 1); |
- if (start > end) throw new RangeError.range(start, 0, end); |
- return end; |
- } |
- |
int get length => _storage.length ~/ 4; |
Int32x4 operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
int _x = _storage[(index * 4) + 0]; |
int _y = _storage[(index * 4) + 1]; |
int _z = _storage[(index * 4) + 2]; |
@@ -298,7 +240,7 @@ class NativeInt32x4List |
} |
void operator[]=(int index, Int32x4 value) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
_storage[(index * 4) + 0] = value.x; |
_storage[(index * 4) + 1] = value.y; |
_storage[(index * 4) + 2] = value.z; |
@@ -306,7 +248,7 @@ class NativeInt32x4List |
} |
List<Int32x4> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
return new NativeInt32x4List._externalStorage( |
_storage.sublist(start * 4, end * 4)); |
} |
@@ -365,57 +307,29 @@ class NativeFloat64x2List |
int get elementSizeInBytes => Float64x2List.BYTES_PER_ELEMENT; |
- void _invalidIndex(int index, int length) { |
- if (index < 0 || index >= length) { |
- if (length == this.length) { |
- throw new RangeError.index(index, this); |
- } |
- throw new RangeError.range(index, 0, length - 1); |
- } else { |
- throw new ArgumentError('Invalid list index $index'); |
- } |
- } |
- |
- void _checkIndex(int index, int length) { |
- if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) { |
- _invalidIndex(index, length); |
- } |
- } |
- |
- int _checkSublistArguments(int start, int end, int length) { |
- // For `sublist` the [start] and [end] indices are allowed to be equal to |
- // [length]. However, [_checkIndex] only allows indices in the range |
- // 0 .. length - 1. We therefore increment the [length] argument by one |
- // for the [_checkIndex] checks. |
- _checkIndex(start, length + 1); |
- if (end == null) return length; |
- _checkIndex(end, length + 1); |
- if (start > end) throw new RangeError.range(start, 0, end); |
- return end; |
- } |
- |
int get length => _storage.length ~/ 2; |
Float64x2 operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
double _x = _storage[(index * 2) + 0]; |
double _y = _storage[(index * 2) + 1]; |
return new Float64x2(_x, _y); |
} |
void operator[]=(int index, Float64x2 value) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
_storage[(index * 2) + 0] = value.x; |
_storage[(index * 2) + 1] = value.y; |
} |
List<Float64x2> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
return new NativeFloat64x2List._externalStorage( |
_storage.sublist(start * 2, end * 2)); |
} |
} |
+@Native("ArrayBufferView") |
class NativeTypedData implements TypedData { |
/** |
* Returns the byte buffer associated with this object. |
@@ -444,38 +358,20 @@ class NativeTypedData implements TypedData { |
@JSName('BYTES_PER_ELEMENT') |
external int get elementSizeInBytes; |
- void _invalidIndex(int index, int length) { |
- if (index < 0 || index >= length) { |
- if (this is List) { |
- // Typed as dynamic to avoid warning. |
- if (length == (this as dynamic).length) { |
- throw new RangeError.index(index, this); |
- } |
- } |
- throw new RangeError.range(index, 0, length - 1); |
+ void _invalidPosition(int position, int length, String name) { |
+ if (position is !int) { |
+ throw new ArgumentError.value(position, name, 'Invalid list position'); |
} else { |
- throw new ArgumentError('Invalid list index $index'); |
+ throw new RangeError.range(position, 0, length, name); |
} |
} |
- void _checkIndex(int index, int length) { |
- if (JS('bool', '(# >>> 0) !== #', index, index) || |
- JS('int', '#', index) >= length) { // 'int' guaranteed by above test. |
- _invalidIndex(index, length); |
+ void _checkPosition(int position, int length, String name) { |
+ if (JS('bool', '(# >>> 0) !== #', position, position) || |
+ JS('int', '#', position) > length) { // 'int' guaranteed by above test. |
+ _invalidPosition(position, length, name); |
} |
} |
- |
- int _checkSublistArguments(int start, int end, int length) { |
- // For `sublist` the [start] and [end] indices are allowed to be equal to |
- // [length]. However, [_checkIndex] only allows indices in the range |
- // 0 .. length - 1. We therefore increment the [length] argument by one |
- // for the [_checkIndex] checks. |
- _checkIndex(start, length + 1); |
- if (end == null) return length; |
- _checkIndex(end, length + 1); |
- if (start > end) throw new RangeError.range(start, 0, end); |
- return end; |
- } |
} |
@@ -862,8 +758,8 @@ abstract class NativeTypedArray extends NativeTypedData |
void _setRangeFast(int start, int end, |
NativeTypedArray source, int skipCount) { |
int targetLength = this.length; |
- _checkIndex(start, targetLength + 1); |
- _checkIndex(end, targetLength + 1); |
+ _checkPosition(start, targetLength, "start"); |
+ _checkPosition(end, targetLength, "end"); |
if (start > end) throw new RangeError.range(start, 0, end); |
int count = end - start; |
@@ -890,12 +786,12 @@ abstract class NativeTypedArrayOfDouble |
int get length => JS('int', '#.length', this); |
double operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('double', '#[#]', this, index); |
} |
void operator[]=(int index, num value) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
JS('void', '#[#] = #', this, index, value); |
} |
@@ -920,7 +816,7 @@ abstract class NativeTypedArrayOfInt |
// types |
void operator[]=(int index, int value) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
JS('void', '#[#] = #', this, index, value); |
} |
@@ -956,7 +852,7 @@ class NativeFloat32List |
Type get runtimeType => Float32List; |
List<double> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeFloat32List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -993,7 +889,7 @@ class NativeFloat64List |
Type get runtimeType => Float64List; |
List<double> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1030,12 +926,12 @@ class NativeInt16List |
Type get runtimeType => Int16List; |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1070,12 +966,12 @@ class NativeInt32List extends NativeTypedArrayOfInt implements Int32List { |
Type get runtimeType => Int32List; |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeInt32List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1110,12 +1006,12 @@ class NativeInt8List extends NativeTypedArrayOfInt implements Int8List { |
Type get runtimeType => Int8List; |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeInt8List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1150,12 +1046,12 @@ class NativeUint16List extends NativeTypedArrayOfInt implements Uint16List { |
Type get runtimeType => Uint16List; |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeUint16List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1190,12 +1086,12 @@ class NativeUint32List extends NativeTypedArrayOfInt implements Uint32List { |
Type get runtimeType => Uint32List; |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeUint32List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1234,12 +1130,12 @@ class NativeUint8ClampedList |
int get length => JS('int', '#.length', this); |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeUint8ClampedList', '#.subarray(#, #)', |
this, start, end); |
return _create1(source); |
@@ -1282,12 +1178,12 @@ class NativeUint8List extends NativeTypedArrayOfInt implements Uint8List { |
int get length => JS('int', '#.length', this); |
int operator[](int index) { |
- _checkIndex(index, length); |
+ _checkValidIndex(index, this, this.length); |
return JS('int', '#[#]', this, index); |
} |
List<int> sublist(int start, [int end]) { |
- end = _checkSublistArguments(start, end, length); |
+ end = _checkValidRange(start, end, this.length); |
var source = JS('NativeUint8List', '#.subarray(#, #)', this, start, end); |
return _create1(source); |
} |
@@ -1544,42 +1440,42 @@ class NativeFloat32x4 implements Float32x4 { |
} |
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. |
- Float32x4 shuffle(int m) { |
- if ((m < 0) || (m > 255)) { |
- throw new RangeError('mask $m must be in the range [0..256)'); |
+ Float32x4 shuffle(int mask) { |
+ if ((mask < 0) || (mask > 255)) { |
+ throw new RangeError.range(mask, 0, 255, "mask"); |
} |
_list[0] = x; |
_list[1] = y; |
_list[2] = z; |
_list[3] = w; |
- double _x = _list[m & 0x3]; |
- double _y = _list[(m >> 2) & 0x3]; |
- double _z = _list[(m >> 4) & 0x3]; |
- double _w = _list[(m >> 6) & 0x3]; |
+ double _x = _list[mask & 0x3]; |
+ double _y = _list[(mask >> 2) & 0x3]; |
+ double _z = _list[(mask >> 4) & 0x3]; |
+ double _w = _list[(mask >> 6) & 0x3]; |
return new NativeFloat32x4._truncated(_x, _y, _z, _w); |
} |
/// Shuffle the lane values in [this] and [other]. The returned |
/// Float32x4 will have XY lanes from [this] and ZW lanes from [other]. |
/// Uses the same [mask] as [shuffle]. |
- Float32x4 shuffleMix(Float32x4 other, int m) { |
- if ((m < 0) || (m > 255)) { |
- throw new RangeError('mask $m must be in the range [0..256)'); |
+ Float32x4 shuffleMix(Float32x4 other, int mask) { |
+ if ((mask < 0) || (mask > 255)) { |
+ throw new RangeError.range(mask, 0, 255, "mask"); |
} |
_list[0] = x; |
_list[1] = y; |
_list[2] = z; |
_list[3] = w; |
- double _x = _list[m & 0x3]; |
- double _y = _list[(m >> 2) & 0x3]; |
+ double _x = _list[mask & 0x3]; |
+ double _y = _list[(mask >> 2) & 0x3]; |
_list[0] = other.x; |
_list[1] = other.y; |
_list[2] = other.z; |
_list[3] = other.w; |
- double _z = _list[(m >> 4) & 0x3]; |
- double _w = _list[(m >> 6) & 0x3]; |
+ double _z = _list[(mask >> 4) & 0x3]; |
+ double _w = _list[(mask >> 6) & 0x3]; |
return new NativeFloat32x4._truncated(_x, _y, _z, _w); |
} |
@@ -1767,7 +1663,7 @@ class NativeInt32x4 implements Int32x4 { |
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. |
Int32x4 shuffle(int mask) { |
if ((mask < 0) || (mask > 255)) { |
- throw new RangeError('mask $mask must be in the range [0..256)'); |
+ throw new RangeError.range(mask, 0, 255, "mask"); |
} |
_list[0] = x; |
_list[1] = y; |
@@ -1785,7 +1681,7 @@ class NativeInt32x4 implements Int32x4 { |
/// Uses the same [mask] as [shuffle]. |
Int32x4 shuffleMix(Int32x4 other, int mask) { |
if ((mask < 0) || (mask > 255)) { |
- throw new RangeError('mask $mask must be in the range [0..256)'); |
+ throw new RangeError.range(mask, 0, 255, "mask"); |
} |
_list[0] = x; |
_list[1] = y; |
@@ -2010,3 +1906,37 @@ class NativeFloat64x2 implements Float64x2 { |
return new NativeFloat64x2._doubles(Math.sqrt(x), Math.sqrt(y)); |
} |
} |
+ |
+/// Checks that the value is a Uint32. If not, it's not valid as an array |
+/// index or offset. Also ensures that the value is non-negative. |
+bool _isInvalidArrayIndex(int index) { |
+ return (JS('bool', '(# >>> 0 !== #)', index, index)); |
+} |
+ |
+/// Checks that [index] is a valid index into [list] which has length [length]. |
+/// |
+/// That is, [index] is an insteger in the range `0..length - 1`. |
+void _checkValidIndex(int index, List list, int length) { |
+ if (_isInvalidArrayIndex(index) || JS('int', '#', index) >= length) { |
+ throw diagnoseIndexError(list, index); |
+ } |
+} |
+ |
+/// Checks that [start] and [end] form a range of a list of length [length]. |
+/// |
+/// That is: `start` and `end` are integers with `0 <= start <= end <= length`. |
+/// If `end` is `null` in which case it is considered to be `length` |
+/// |
+/// Returns the actual value of `end`, which is `length` if `end` is `null`, and |
+/// the original value of `end` otherwise. |
+int _checkValidRange(int start, int end, int length) { |
+ if (_isInvalidArrayIndex(start) || // Ensures start is non-negative int. |
+ ((end == null) ? start > length |
+ : (_isInvalidArrayIndex(end) || |
+ start > end || |
+ end > length))) { |
+ throw diagnoseRangeError(start, end, length); |
+ } |
+ if (end == null) return length; |
+ return end; |
+} |