Commit 60e674c1 authored by dehrenberg's avatar dehrenberg Committed by Commit bot

TypedArray.prototype.every method

BUG=v8:3578
LOG=Y
R=adamk@chromium.org, dslomov@chromium.org, svenpanne@chromium.org

Review URL: https://codereview.chromium.org/1128273002

Cr-Commit-Position: refs/heads/master@{#28301}
parent ae6a0b80
......@@ -31,6 +31,40 @@ TYPED_ARRAYS(DECLARE_GLOBALS)
macro TYPED_ARRAY_HARMONY_ADDITIONS(ARRAY_ID, NAME, ELEMENT_SIZE)
// ES6 draft 05-05-15, section 22.2.3.7
function NAMEEvery(f /* thisArg */) { // length == 1
if (!%IsTypedArray(this)) {
throw MakeTypeError('not_typed_array', []);
}
if (!IS_SPEC_FUNCTION(f)) throw MakeTypeError(kCalledNonCallable, f);
var length = %_TypedArrayGetLength(this);
var receiver;
if (%_ArgumentsLength() > 1) {
receiver = %_Arguments(1);
}
var needs_wrapper = false;
if (IS_NULL(receiver)) {
if (%IsSloppyModeFunction(mapfn)) receiver = UNDEFINED;
} else if (!IS_UNDEFINED(receiver)) {
needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
}
var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
for (var i = 0; i < length; i++) {
var element = this[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
if (!%_CallFunction(new_receiver, TO_OBJECT_INLINE(element), i, this, f)) {
return false;
}
}
return true;
}
// ES6 draft 08-24-14, section 22.2.3.12
function NAMEForEach(f /* thisArg */) { // length == 1
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
......@@ -83,6 +117,7 @@ macro EXTEND_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
// Set up non-enumerable functions on the prototype object.
$installFunctions(GlobalNAME.prototype, DONT_ENUM, [
"every", NAMEEvery,
"forEach", NAMEForEach
]);
endmacro
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-arrays --allow-natives-syntax
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array];
function CheckTypedArrayIsNeutered(array) {
assertEquals(0, array.byteLength);
assertEquals(0, array.byteOffset);
assertEquals(0, array.length);
}
function TestTypedArrayForEach(constructor) {
assertEquals(1, constructor.prototype.every.length);
var a = new constructor(3);
a[0] = 0;
a[1] = 1;
a[2] = 2;
var result = a.every(function (n) { return n < 2; });
assertFalse(result);
var result = a.every(function (n) { return n > 2; });
assertFalse(result);
var result = a.every(function (n) { return n >= 0; });
assertEquals(true, result);
// Use specified object as this object when calling the function.
var o = { value: 42 };
result = a.every(function (n, index, array) { return n == index && n < this.value; }, o);
assertEquals(true, result);
// Early exit happens when appropriate
count = 0;
result = a.every(function () { count++; return false; });
assertEquals(1, count);
assertFalse(result);
// Modify the original array.
count = 0;
result = a.every(function (n, index, array) {
array[index] = n + 1; count++; return true;
});
assertEquals(3, count);
assertEquals(true, result);
assertArrayEquals([1, 2, 3], a);
// Check that values passed as second argument are wrapped into
// objects when calling into sloppy mode functions.
function CheckWrapping(value, wrapper) {
var wrappedValue = new wrapper(value);
a.every(function () {
assertEquals("object", typeof this);
assertEquals(wrappedValue, this);
}, value);
a.every(function () {
"use strict";
assertEquals(typeof value, typeof this);
assertEquals(value, this);
}, value);
}
CheckWrapping(true, Boolean);
CheckWrapping(false, Boolean);
CheckWrapping("xxx", String);
CheckWrapping(42, Number);
CheckWrapping(3.14, Number);
CheckWrapping({}, Object);
// Neutering the buffer backing the typed array mid-way should
// still make .forEach() finish, and the array should keep being
// empty after neutering it.
count = 0;
a = new constructor(2);
result = a.every(function (n, index, array) {
if (count > 0) %ArrayBufferNeuter(array.buffer);
array[index] = n + 1;
count++;
return count > 1 ? array[index] === undefined : true;
});
assertEquals(2, count);
assertEquals(true, result);
CheckTypedArrayIsNeutered(a);
assertEquals(undefined, a[0]);
// The method must work for typed arrays created from ArrayBuffer.
// The length of the ArrayBuffer is chosen so it is a multiple of
// all lengths of the typed array items.
a = new constructor(new ArrayBuffer(64));
count = 0;
result = a.every(function (n) { return n == 0; });
assertEquals(result, true);
// Externalizing the array mid-way accessing the .buffer property
// should work.
a = new constructor(2);
count = 0;
var buffer = undefined;
a.every(function (n, index, array) {
if (count++ > 0)
buffer = array.buffer;
return true;
});
assertEquals(2, count);
assertTrue(!!buffer);
assertEquals("ArrayBuffer", %_ClassOf(buffer));
assertSame(buffer, a.buffer);
// The %TypedArray%.every() method should not work when
// transplanted to objects that are not typed arrays.
assertThrows(function () { constructor.prototype.every.call([1, 2, 3], function (x) {}) }, TypeError);
assertThrows(function () { constructor.prototype.every.call("abc", function (x) {}) }, TypeError);
assertThrows(function () { constructor.prototype.every.call({}, function (x) {}) }, TypeError);
assertThrows(function () { constructor.prototype.every.call(0, function (x) {}) }, TypeError);
// Method must be useable on instances of other typed arrays.
for (var i = 0; i < typedArrayConstructors.length; i++) {
count = 0;
a = new typedArrayConstructors[i](4);
constructor.prototype.every.call(a, function (x) { count++; return true; });
assertEquals(a.length, count);
}
}
for (i = 0; i < typedArrayConstructors.length; i++) {
TestTypedArrayForEach(typedArrayConstructors[i]);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment