Update typed arrays behavior to match ES6 rev 15. Remove TO_POSITIVE_INTEGER and throw on negative length arguments.
R=rossberg@chromium.org Review URL: https://codereview.chromium.org/17572009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15298 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8db56239a0
commit
e6e0ee0708
@ -31,12 +31,12 @@ var $ArrayBuffer = global.ArrayBuffer;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function ArrayBufferConstructor(byteLength) { // length = 1
|
||||
function ArrayBufferConstructor(length) { // length = 1
|
||||
if (%_IsConstructCall()) {
|
||||
var l = TO_POSITIVE_INTEGER(byteLength);
|
||||
%ArrayBufferInitialize(this, l);
|
||||
var byteLength = ToPositiveInteger(length, 'invalid_array_buffer_length');
|
||||
%ArrayBufferInitialize(this, byteLength);
|
||||
} else {
|
||||
return new $ArrayBuffer(byteLength);
|
||||
return new $ArrayBuffer(length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +70,9 @@ function ArrayBufferSlice(start, end) {
|
||||
fin = MathMin(relativeEnd, this.byteLength);
|
||||
}
|
||||
|
||||
if (fin < first) {
|
||||
fin = first;
|
||||
}
|
||||
var newLen = fin - first;
|
||||
// TODO(dslomov): implement inheritance
|
||||
var result = new $ArrayBuffer(newLen);
|
||||
|
@ -145,7 +145,6 @@ const kBoundArgumentsStartIndex = 2;
|
||||
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
|
||||
macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
|
||||
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
|
||||
macro TO_POSITIVE_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? (arg > 0 ? arg : 0) : %NumberToPositiveInteger(ToNumber(arg)));
|
||||
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
|
||||
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
|
||||
macro TO_UINT32(arg) = (arg >>> 0);
|
||||
|
@ -112,13 +112,15 @@ var kMessages = {
|
||||
// RangeError
|
||||
invalid_array_length: ["Invalid array length"],
|
||||
invalid_array_buffer_length: ["Invalid array buffer length"],
|
||||
invalid_typed_array_offset: ["Start offset is too large"],
|
||||
invalid_typed_array_length: ["Length is too large"],
|
||||
invalid_typed_array_offset: ["Start offset is too large:"],
|
||||
invalid_typed_array_length: ["Invalid typed array length"],
|
||||
invalid_typed_array_alignment: ["%0", "of", "%1", "should be a multiple of", "%3"],
|
||||
typed_array_set_source_too_large:
|
||||
["Source is too large"],
|
||||
typed_array_set_negative_offset:
|
||||
["Start offset is negative"],
|
||||
invalid_data_view_offset: ["Start offset is outside the bounds of the buffer"],
|
||||
invalid_data_view_length: ["Length is too large"],
|
||||
invalid_data_view_length: ["Invalid data view length"],
|
||||
invalid_data_view_accessor_offset:
|
||||
["Offset is outside the bounds of the DataView"],
|
||||
|
||||
|
@ -658,7 +658,6 @@ function DefaultNumber(x) {
|
||||
throw %MakeTypeError('cannot_convert_to_primitive', []);
|
||||
}
|
||||
|
||||
|
||||
// ECMA-262, section 8.6.2.6, page 28.
|
||||
function DefaultString(x) {
|
||||
var toString = x.toString;
|
||||
@ -676,6 +675,12 @@ function DefaultString(x) {
|
||||
throw %MakeTypeError('cannot_convert_to_primitive', []);
|
||||
}
|
||||
|
||||
function ToPositiveInteger(x, rangeErrorName) {
|
||||
var i = TO_INTEGER(x);
|
||||
if (i < 0) throw %MakeRangeError(rangeErrorName);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Setting the prototype for Array must take place as early as
|
||||
// possible due to code generation for array literals. When
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
|
||||
function ConstructByArrayBuffer(obj, buffer, byteOffset, length) {
|
||||
var offset = IS_UNDEFINED(byteOffset) ? 0 : TO_POSITIVE_INTEGER(byteOffset);
|
||||
var offset = ToPositiveInteger(byteOffset, "invalid_typed_array_length")
|
||||
|
||||
if (offset % elementSize !== 0) {
|
||||
throw MakeRangeError("invalid_typed_array_alignment",
|
||||
@ -58,7 +58,7 @@ function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
|
||||
newByteLength = bufferByteLength - offset;
|
||||
newLength = newByteLength / elementSize;
|
||||
} else {
|
||||
var newLength = TO_POSITIVE_INTEGER(length);
|
||||
var newLength = ToPositiveInteger(length, "invalid_typed_array_length");
|
||||
newByteLength = newLength * elementSize;
|
||||
}
|
||||
if (offset + newByteLength > bufferByteLength) {
|
||||
@ -68,7 +68,7 @@ function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
|
||||
}
|
||||
|
||||
function ConstructByLength(obj, length) {
|
||||
var l = IS_UNDEFINED(length) ? 0 : TO_POSITIVE_INTEGER(length);
|
||||
var l = ToPositiveInteger(length, "invalid_typed_array_length");
|
||||
var byteLength = l * elementSize;
|
||||
var buffer = new global.ArrayBuffer(byteLength);
|
||||
%TypedArrayInitialize(obj, arrayId, buffer, 0, byteLength);
|
||||
@ -76,7 +76,7 @@ function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
|
||||
|
||||
function ConstructByArrayLike(obj, arrayLike) {
|
||||
var length = arrayLike.length;
|
||||
var l = IS_UNDEFINED(length) ? 0 : TO_POSITIVE_INTEGER(length);
|
||||
var l = ToPositiveInteger(length, "invalid_typed_array_length");
|
||||
var byteLength = l * elementSize;
|
||||
var buffer = new $ArrayBuffer(byteLength);
|
||||
%TypedArrayInitialize(obj, arrayId, buffer, 0, byteLength);
|
||||
@ -146,7 +146,10 @@ function CreateSubArray(elementSize, constructor) {
|
||||
}
|
||||
|
||||
function TypedArraySet(obj, offset) {
|
||||
var intOffset = IS_UNDEFINED(offset) ? 0 : TO_POSITIVE_INTEGER(offset);
|
||||
var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
|
||||
if (intOffset < 0) {
|
||||
throw MakeTypeError("typed_array_set_negative_offset");
|
||||
}
|
||||
if (%TypedArraySetFastCases(this, obj, intOffset))
|
||||
return;
|
||||
|
||||
@ -209,13 +212,13 @@ function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3
|
||||
throw MakeTypeError('data_view_not_array_buffer', []);
|
||||
}
|
||||
var bufferByteLength = %ArrayBufferGetByteLength(buffer);
|
||||
var offset = IS_UNDEFINED(byteOffset) ? 0 : TO_POSITIVE_INTEGER(byteOffset);
|
||||
var offset = ToPositiveInteger(byteOffset, 'invalid_data_view_offset');
|
||||
if (offset > bufferByteLength) {
|
||||
throw MakeRangeError('invalid_data_view_offset', []);
|
||||
throw MakeRangeError('invalid_data_view_offset');
|
||||
}
|
||||
var length = IS_UNDEFINED(byteLength) ?
|
||||
bufferByteLength - offset : TO_POSITIVE_INTEGER(byteLength);
|
||||
if (offset + length > bufferByteLength) {
|
||||
bufferByteLength - offset : TO_INTEGER(byteLength);
|
||||
if (length < 0 || offset + length > bufferByteLength) {
|
||||
throw new MakeRangeError('invalid_data_view_length');
|
||||
}
|
||||
%DataViewInitialize(this, buffer, offset, length);
|
||||
@ -248,12 +251,18 @@ function DataViewGetByteLength() {
|
||||
return %DataViewGetByteLength(this);
|
||||
}
|
||||
|
||||
function ToPositiveDataViewOffset(offset) {
|
||||
return ToPositiveInteger(offset, 'invalid_data_view_accessor_offset');
|
||||
}
|
||||
|
||||
function DataViewGetInt8(offset, little_endian) {
|
||||
if (!IS_DATAVIEW(this)) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getInt8', this]);
|
||||
}
|
||||
return %DataViewGetInt8(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetInt8(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetInt8(offset, value, little_endian) {
|
||||
@ -262,7 +271,7 @@ function DataViewSetInt8(offset, value, little_endian) {
|
||||
['DataView.setInt8', this]);
|
||||
}
|
||||
%DataViewSetInt8(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -272,7 +281,9 @@ function DataViewGetUint8(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getUint8', this]);
|
||||
}
|
||||
return %DataViewGetUint8(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetUint8(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetUint8(offset, value, little_endian) {
|
||||
@ -281,7 +292,7 @@ function DataViewSetUint8(offset, value, little_endian) {
|
||||
['DataView.setUint8', this]);
|
||||
}
|
||||
%DataViewSetUint8(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -291,7 +302,9 @@ function DataViewGetInt16(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getInt16', this]);
|
||||
}
|
||||
return %DataViewGetInt16(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetInt16(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetInt16(offset, value, little_endian) {
|
||||
@ -300,7 +313,7 @@ function DataViewSetInt16(offset, value, little_endian) {
|
||||
['DataView.setInt16', this]);
|
||||
}
|
||||
%DataViewSetInt16(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -310,7 +323,9 @@ function DataViewGetUint16(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getUint16', this]);
|
||||
}
|
||||
return %DataViewGetUint16(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetUint16(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetUint16(offset, value, little_endian) {
|
||||
@ -319,7 +334,7 @@ function DataViewSetUint16(offset, value, little_endian) {
|
||||
['DataView.setUint16', this]);
|
||||
}
|
||||
%DataViewSetUint16(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -329,7 +344,9 @@ function DataViewGetInt32(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getInt32', this]);
|
||||
}
|
||||
return %DataViewGetInt32(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetInt32(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetInt32(offset, value, little_endian) {
|
||||
@ -338,7 +355,7 @@ function DataViewSetInt32(offset, value, little_endian) {
|
||||
['DataView.setInt32', this]);
|
||||
}
|
||||
%DataViewSetInt32(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -348,7 +365,9 @@ function DataViewGetUint32(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getUint32', this]);
|
||||
}
|
||||
return %DataViewGetUint32(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetUint32(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetUint32(offset, value, little_endian) {
|
||||
@ -357,7 +376,7 @@ function DataViewSetUint32(offset, value, little_endian) {
|
||||
['DataView.setUint32', this]);
|
||||
}
|
||||
%DataViewSetUint32(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -367,7 +386,9 @@ function DataViewGetFloat32(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getFloat32', this]);
|
||||
}
|
||||
return %DataViewGetFloat32(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
return %DataViewGetFloat32(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetFloat32(offset, value, little_endian) {
|
||||
@ -376,7 +397,7 @@ function DataViewSetFloat32(offset, value, little_endian) {
|
||||
['DataView.setFloat32', this]);
|
||||
}
|
||||
%DataViewSetFloat32(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
@ -386,7 +407,13 @@ function DataViewGetFloat64(offset, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.getFloat64', this]);
|
||||
}
|
||||
return %DataViewGetFloat64(this, TO_POSITIVE_INTEGER(offset), !!little_endian);
|
||||
offset = TO_INTEGER(offset);
|
||||
if (offset < 0) {
|
||||
throw MakeRangeError("invalid_data_view_accessor_offset");
|
||||
}
|
||||
return %DataViewGetFloat64(this,
|
||||
ToPositiveDataViewOffset(offset),
|
||||
!!little_endian);
|
||||
}
|
||||
|
||||
function DataViewSetFloat64(offset, value, little_endian) {
|
||||
@ -394,8 +421,12 @@ function DataViewSetFloat64(offset, value, little_endian) {
|
||||
throw MakeTypeError('incompatible_method_reciever',
|
||||
['DataView.setFloat64', this]);
|
||||
}
|
||||
offset = TO_INTEGER(offset);
|
||||
if (offset < 0) {
|
||||
throw MakeRangeError("invalid_data_view_accessor_offset");
|
||||
}
|
||||
%DataViewSetFloat64(this,
|
||||
TO_POSITIVE_INTEGER(offset),
|
||||
ToPositiveDataViewOffset(offset),
|
||||
TO_NUMBER_INLINE(value),
|
||||
!!little_endian);
|
||||
}
|
||||
|
@ -64,8 +64,7 @@ function checkGet(func, index, expected, littleEndian) {
|
||||
function doGet() {
|
||||
return view["get" + func](index, littleEndian);
|
||||
}
|
||||
if (index < 0) index = 0;
|
||||
if (index + getElementSize(func) - 1 < view.byteLength)
|
||||
if (index >=0 && index + getElementSize(func) - 1 < view.byteLength)
|
||||
assertSame(expected, doGet());
|
||||
else
|
||||
assertThrows(doGet, RangeError);
|
||||
@ -75,9 +74,8 @@ function checkSet(func, index, value, littleEndian) {
|
||||
function doSet() {
|
||||
view["set" + func](index, value, littleEndian);
|
||||
}
|
||||
actualIndex = index < 0 ? 0 : index;
|
||||
if (actualIndex >= 0 &&
|
||||
actualIndex + getElementSize(func) - 1 < view.byteLength) {
|
||||
if (index >= 0 &&
|
||||
index + getElementSize(func) - 1 < view.byteLength) {
|
||||
assertSame(undefined, doSet());
|
||||
checkGet(func, index, value, littleEndian);
|
||||
} else {
|
||||
|
@ -35,14 +35,15 @@ function TestByteLength(param, expectedByteLength) {
|
||||
function TestArrayBufferCreation() {
|
||||
TestByteLength(1, 1);
|
||||
TestByteLength(256, 256);
|
||||
TestByteLength(-10, 0);
|
||||
TestByteLength(2.567, 2);
|
||||
TestByteLength(-2.567, 0);
|
||||
|
||||
TestByteLength("abc", 0);
|
||||
|
||||
TestByteLength(0, 0);
|
||||
|
||||
assertThrows(function() { new ArrayBuffer(-10); }, RangeError);
|
||||
assertThrows(function() { new ArrayBuffer(-2.567); }, RangeError);
|
||||
|
||||
/* TODO[dslomov]: Reenable the test
|
||||
assertThrows(function() {
|
||||
var ab1 = new ArrayBuffer(0xFFFFFFFFFFFF)
|
||||
@ -89,6 +90,7 @@ function TestArrayBufferSlice() {
|
||||
TestSlice(0, 0, 1, 20);
|
||||
TestSlice(100, 100, 0, 100);
|
||||
TestSlice(100, 100, 0, 1000);
|
||||
|
||||
TestSlice(0, 100, 5, 1);
|
||||
|
||||
TestSlice(1, 100, -11, -10);
|
||||
@ -99,7 +101,7 @@ function TestArrayBufferSlice() {
|
||||
TestSlice(10, 100, 90, "100");
|
||||
TestSlice(10, 100, "90", "100");
|
||||
|
||||
TestSlice(0, 100, 90, "abc");
|
||||
TestSlice(0, 100, 90, "abc");
|
||||
TestSlice(10, 100, "abc", 10);
|
||||
|
||||
TestSlice(10, 100, 0.96, 10.96);
|
||||
@ -107,7 +109,6 @@ function TestArrayBufferSlice() {
|
||||
TestSlice(10, 100, 0.01, 10.01);
|
||||
TestSlice(10, 100, 0.01, 10.96);
|
||||
|
||||
|
||||
TestSlice(10, 100, 90);
|
||||
TestSlice(10, 100, -10);
|
||||
}
|
||||
@ -489,24 +490,15 @@ function TestDataViewConstructor() {
|
||||
assertSame(256, d3c.byteOffset);
|
||||
assertSame(0, d3c.byteLength);
|
||||
|
||||
// weird args
|
||||
var d4 = new DataView(ab, -1);
|
||||
var d4 = new DataView(ab, 1, 3.1415926);
|
||||
assertSame(ab, d4.buffer);
|
||||
assertSame(0, d4.byteOffset);
|
||||
assertSame(256, d4.byteLength);
|
||||
|
||||
var d5 = new DataView(ab, 1, -1);
|
||||
assertSame(ab, d5.buffer);
|
||||
assertSame(1, d5.byteOffset);
|
||||
assertSame(0, d5.byteLength);
|
||||
|
||||
var d6 = new DataView(ab, 1, 3.1415926);
|
||||
assertSame(ab, d6.buffer);
|
||||
assertSame(1, d6.byteOffset);
|
||||
assertSame(3, d6.byteLength);
|
||||
assertSame(1, d4.byteOffset);
|
||||
assertSame(3, d4.byteLength);
|
||||
|
||||
|
||||
// error cases
|
||||
assertThrows(function() { new DataView(ab, -1); }, RangeError);
|
||||
assertThrows(function() { new DataView(ab, 1, -1); }, RangeError);
|
||||
assertThrows(function() { new DataView(); }, TypeError);
|
||||
assertThrows(function() { new DataView([]); }, TypeError);
|
||||
assertThrows(function() { new DataView(ab, 257); }, RangeError);
|
||||
|
Loading…
Reference in New Issue
Block a user