typedarray-every.js 5.23 KB
Newer Older
1 2 3 4
// 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.

5
// Flags: --allow-natives-syntax
6 7 8 9 10 11 12 13 14 15 16 17

var typedArrayConstructors = [
  Uint8Array,
  Int8Array,
  Uint16Array,
  Int16Array,
  Uint32Array,
  Int32Array,
  Uint8ClampedArray,
  Float32Array,
  Float64Array];

18
function CheckTypedArrayIsDetached(array) {
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
  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);

84
  // Detaching the buffer backing the typed array mid-way should
85
  // still make .forEach() finish, and the array should keep being
86
  // empty after detaching it.
87
  count = 0;
88
  a = new constructor(3);
89
  result = a.every(function (n, index, array) {
90 91
    assertFalse(array[index] === undefined);  // don't get here if detached
    if (count > 0) %ArrayBufferDetach(array.buffer);
92 93 94 95 96 97
    array[index] = n + 1;
    count++;
    return count > 1 ? array[index] === undefined : true;
  });
  assertEquals(2, count);
  assertEquals(true, result);
98
  CheckTypedArrayIsDetached(a);
99 100
  assertEquals(undefined, a[0]);

101 102 103 104 105 106 107 108 109 110 111 112 113 114
  // Calling array.buffer midway can change the backing store.
  a = new constructor(5);
  a[0] = 42;
  result = a.every(function (n, index, array) {
    assertSame(a, array);
    if (index == 2) {
      (new constructor(array.buffer))[(index + 1) % 5] = 42;
    } else {
      a[(index+1)%5] = 42
    }
    return n == 42;
  });
  assertEquals(true, result);

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
  // 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);
  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);
  }
151 152 153 154 155 156 157 158 159 160

  // Shadowing length doesn't affect every, unlike Array.prototype.every
  a = new constructor([1, 2]);
  Object.defineProperty(a, 'length', {value: 1});
  var x = 0;
  assertEquals(a.every(function(elt) { x += elt; return true; }), true);
  assertEquals(x, 3);
  assertEquals(Array.prototype.every.call(a,
      function(elt) { x += elt; return true; }), true);
  assertEquals(x, 4);
161 162 163

  // Detached Operation
  var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
164
  %ArrayBufferDetach(array.buffer);
165
  assertThrows(() => array.every(() => true), TypeError);
166 167 168 169 170
}

for (i = 0; i < typedArrayConstructors.length; i++) {
  TestTypedArrayForEach(typedArrayConstructors[i]);
}