From: dehrenberg Date: Thu, 7 May 2015 15:54:16 +0000 (-0700) Subject: TypedArray.prototype.every method X-Git-Tag: upstream/4.7.83~2739 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=60e674c11efd62a8bdd086916e489476484eedd8;p=platform%2Fupstream%2Fv8.git 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} --- diff --git a/src/harmony-typedarray.js b/src/harmony-typedarray.js index 9b7cd0deb..5b666b564 100644 --- a/src/harmony-typedarray.js +++ b/src/harmony-typedarray.js @@ -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 diff --git a/test/mjsunit/harmony/typedarrays-every.js b/test/mjsunit/harmony/typedarrays-every.js new file mode 100644 index 000000000..3f95ba9d4 --- /dev/null +++ b/test/mjsunit/harmony/typedarrays-every.js @@ -0,0 +1,141 @@ +// 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]); +}