mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
6.8 KiB
289 lines
6.8 KiB
/*
|
|
* ArrayBuffer constructor
|
|
*/
|
|
|
|
/*@include util-typedarray.js@*/
|
|
|
|
/*---
|
|
{
|
|
"custom": true
|
|
}
|
|
---*/
|
|
|
|
function str(x) {
|
|
if (typeof x === 'function') { return '[function]'; }
|
|
return String(x);
|
|
}
|
|
|
|
/*===
|
|
string NONE object 0 0 0 1
|
|
undefined undefined object 0 0 0 1
|
|
object null object 0 0 0 1
|
|
boolean true object 1 1 0 1
|
|
boolean false object 0 0 0 1
|
|
string foo object 0 0 0 1
|
|
string 123 object 123 123 0 1
|
|
object 123 object 123 123 0 1
|
|
object [object Object] object 0 0 0 1
|
|
function [function] object 0 0 0 1
|
|
object [object Object] object 321 321 0 1
|
|
number -Infinity RangeError
|
|
number -1000000000 RangeError
|
|
number -1 RangeError
|
|
number 0 object 0 0 0 1
|
|
number 1 object 1 1 0 1
|
|
number 100 object 100 100 0 1
|
|
number 1000000 object 1000000 1000000 0 1
|
|
number Infinity RangeError
|
|
number NaN object 0 0 0 1
|
|
===*/
|
|
|
|
function arrayBufferConstructorTest() {
|
|
/*
|
|
* TypedArray spec only provides: new ArrayBuffer(unsigned long length).
|
|
*
|
|
* Duktape uses a ToInteger() coercion for the argument so it accepts a
|
|
* wider range of arguments.
|
|
*/
|
|
|
|
[
|
|
'NONE', undefined, null, true, false, 'foo', '123', [ '123' ],
|
|
{ foo: 'bar' }, function func() {},
|
|
{ valueOf: function () { return 321; } },
|
|
-1 / 0, -1e9, -1, 0, 1, 100, 1e6, 1 / 0, 0 / 0
|
|
].forEach(function (arg) {
|
|
var b;
|
|
try {
|
|
if (arg === 'NONE') {
|
|
b = new ArrayBuffer();
|
|
} else {
|
|
b = new ArrayBuffer(arg);
|
|
}
|
|
print(typeof arg, str(arg), typeof b, b.length, b.byteLength, b.byteOffset, b.BYTES_PER_ELEMENT);
|
|
|
|
if (typeof b.byteLength === 'number') {
|
|
for (var i = 0; i < b.byteLength; i++) {
|
|
if (b[i] != 0) {
|
|
throw new Error('arraybuffer not zeroed as expected, non-zero byte at index: ' + i);
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print(typeof arg, str(arg), e.name);
|
|
}
|
|
});
|
|
}
|
|
|
|
try {
|
|
arrayBufferConstructorTest();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|
|
/*===
|
|
TypeError
|
|
===*/
|
|
|
|
/* ArrayBuffer cannot be called as a normal function. */
|
|
|
|
function arrayBufferNormalCallTest() {
|
|
var buf = ArrayBuffer(10);
|
|
print(typeof buf); // Never here
|
|
}
|
|
|
|
try {
|
|
arrayBufferNormalCallTest();
|
|
} catch (e) {
|
|
print(e.name);
|
|
}
|
|
|
|
/*===
|
|
ArrayBuffer constructor call test
|
|
[object ArrayBuffer]
|
|
[object ArrayBuffer]
|
|
true
|
|
[object ArrayBuffer] -> ArrayBuffer.prototype -> Object.prototype
|
|
true false false false
|
|
true
|
|
[object ArrayBuffer]
|
|
ArrayBuffer normal call test
|
|
TypeError
|
|
===*/
|
|
|
|
function arrayBufferConstructorCallTest(constructorCall) {
|
|
var b;
|
|
var pd;
|
|
|
|
if (constructorCall) {
|
|
b = new ArrayBuffer(16);
|
|
} else {
|
|
b = ArrayBuffer(16);
|
|
}
|
|
|
|
print(String(b));
|
|
print(Object.prototype.toString.call(b));
|
|
|
|
// The required internal prototype is the initial value of
|
|
// ArrayBuffer.prototype (%ArrayBufferPrototype%), with
|
|
// writable = enumerable = configurable = false.
|
|
|
|
print(Object.getPrototypeOf(b) === ArrayBuffer.prototype);
|
|
printPrototypeChain(b);
|
|
|
|
pd = Object.getOwnPropertyDescriptor(ArrayBuffer, 'prototype') || {};
|
|
print(pd.value === Object.getPrototypeOf(b), pd.writable, pd.enumerable, pd.configurable);
|
|
|
|
// .toString() is inherited from Object.prototype
|
|
print(b.toString === Object.prototype.toString);
|
|
print(b.toString());
|
|
}
|
|
|
|
try {
|
|
print('ArrayBuffer constructor call test');
|
|
arrayBufferConstructorCallTest(true);
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|
|
try {
|
|
print('ArrayBuffer normal call test');
|
|
arrayBufferConstructorCallTest(false);
|
|
} catch (e) {
|
|
print(e.name);
|
|
}
|
|
|
|
/*===
|
|
ArrayBuffer array-like test
|
|
0
|
|
===*/
|
|
|
|
/* There's no constructor variant for an Array-like initializer, although such
|
|
* an initializer is accepted by e.g. V8. Test for the compliant behavior, i.e.
|
|
* reject such a call; constructor argument is ToNumber() + ToLength() coerced.
|
|
*/
|
|
|
|
function arrayBufferArrayLikeTest() {
|
|
// Because ToNumber([1, 2, 3]) is NaN, it ToLength() coerces to 0, and the
|
|
// result is a 0-length ArrayBuffer.
|
|
|
|
var b = new ArrayBuffer([ 1, 2, 3 ]);
|
|
|
|
print(b.byteLength);
|
|
}
|
|
|
|
try {
|
|
print('ArrayBuffer array-like test');
|
|
arrayBufferArrayLikeTest();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|
|
/*===
|
|
ArrayBuffer argument test
|
|
NONE 0
|
|
undefined 0
|
|
null 0
|
|
true 1
|
|
false 0
|
|
3 3
|
|
3.9 3
|
|
-1 RangeError
|
|
-1.5 RangeError
|
|
0 0
|
|
0 0
|
|
NaN 0
|
|
268435456 268435456
|
|
1073741824 1073741824
|
|
4294967296 RangeError
|
|
[object Object] 17
|
|
===*/
|
|
|
|
/* Test the ArrayBuffer argument coercion.
|
|
*
|
|
* Currently Duktape doesn't follow ES6 ToLength() (which *clamps* to
|
|
* [0,2^53-1]).
|
|
*/
|
|
|
|
function arrayBufferArgumentTest() {
|
|
var b;
|
|
var MB = 1024 * 1024;
|
|
|
|
[
|
|
'NONE',
|
|
|
|
// Undefined ToNumber() coerces to NaN and fails the final
|
|
// SameValueZero() comparison.
|
|
|
|
undefined,
|
|
|
|
// Null ToNumber() coerces to zero so it's accepted.
|
|
null,
|
|
|
|
// True ToNumber() coerces to 1 and false to 0, both accepted.
|
|
|
|
true,
|
|
false,
|
|
|
|
// ES6 requires that ToNumber(arg) match ToLength(ToNumber(arg))
|
|
// (using SameValueZero which ignores zero sign). In other words,
|
|
// fractional input values cause a RangeError. V8 doesn't follow
|
|
// this behavior but truncates instead.
|
|
|
|
3,
|
|
3.9,
|
|
|
|
// Negative values are coerced to zero by ToLength(). But, later on
|
|
// ToNumber(arg) and ToLength(ToNumber(arg)) are compared to ensure
|
|
// that they match with SameValueZero. If not, a RangeError should
|
|
// happen. So a negative value should RangeError.
|
|
|
|
-1,
|
|
-1.5,
|
|
|
|
// Negative zero is explicitly allowed by ES6, the SameValueZero()
|
|
// comparison ignores zero sign.
|
|
|
|
-0,
|
|
+0,
|
|
|
|
// NaN is not allowed: it coerces to zero but won't pass the
|
|
// SameValueZero() comparison.
|
|
|
|
0 / 0,
|
|
|
|
// Test that 256MB allocation works
|
|
|
|
256 * MB,
|
|
|
|
// Test that 1GB allocation works -- note that this fails on V8/Node.js.
|
|
|
|
1024 * MB,
|
|
|
|
// For now there's an internal maximum buffer length in Duktape.
|
|
// It is triggered at least by 2^32 so test for that. Exceeding
|
|
// the limit causes a RangeError. ES6 doesn't specify what to do
|
|
// if an internal limit is reached but a RangeError seems suitable
|
|
// and matches V8.
|
|
|
|
4096 * MB,
|
|
{ valueOf: function () { return 17; } },
|
|
].forEach(function (arg) {
|
|
try {
|
|
if (arg === 'NONE') {
|
|
b = new ArrayBuffer();
|
|
} else {
|
|
b = new ArrayBuffer(arg); // ToNumber() floors -> 3
|
|
}
|
|
print(arg, b.byteLength);
|
|
} catch (e) {
|
|
print(arg, e.name);
|
|
}
|
|
});
|
|
}
|
|
|
|
try {
|
|
print('ArrayBuffer argument test');
|
|
arrayBufferArgumentTest();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|