v8_mock_archs.js 3.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2017 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.

// This is intended for permanent JS behavior changes for mocking out
// non-deterministic behavior. For temporary suppressions, please refer to
// v8_suppressions.js.
// This mocks only architecture specific differences. Refer to v8_mocks.js
// for the general case.
// This file is loaded before each correctness test cases and won't get
// minimized.

13 14 15 16
// Mock maximum typed-array buffer and limit to 1MiB. Otherwise we might
// get range errors. We ignore those by crashing, but that reduces coverage,
// hence, let's reduce the range-error rate.
(function() {
17
  // Math.min might be manipulated in test cases.
18 19 20 21 22
  const min = Math.min;
  const maxBytes = 1048576;
  const mock = function(type) {
    const maxLength = maxBytes / (type.BYTES_PER_ELEMENT || 1);
    const handler = {
23
      construct: function(target, args) {
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
        if (args[0] && typeof args[0] != "object") {
          // Length used as first argument.
          args[0] = min(maxLength, Number(args[0]));
        } else if (args[0] instanceof ArrayBuffer && args.length > 1) {
          // Buffer used as first argument.
          const buffer = args[0];
          args[1] = Number(args[1]);
          // Ensure offset is multiple of bytes per element.
          args[1] = args[1] - (args[1] % type.BYTES_PER_ELEMENT);
          // Limit offset to length of buffer.
          args[1] = min(args[1], buffer.byteLength || 0);
          if (args.length > 2) {
            // If also length is given, limit it to the maximum that's possible
            // given buffer and offset.
            const maxBytesLeft = buffer.byteLength - args[1];
            const maxLengthLeft = maxBytesLeft / type.BYTES_PER_ELEMENT;
            args[2] = min(Number(args[2]), maxLengthLeft);
41
          }
42
        }
43
        return new (Function.prototype.bind.apply(type, [null].concat(args)));
44 45
      },
    };
46
    return new Proxy(type, handler);
47 48 49
  }

  ArrayBuffer = mock(ArrayBuffer);
50
  SharedArrayBuffer = mock(SharedArrayBuffer);
51 52 53 54 55 56 57
  Int8Array = mock(Int8Array);
  Uint8Array = mock(Uint8Array);
  Uint8ClampedArray = mock(Uint8ClampedArray);
  Int16Array = mock(Int16Array);
  Uint16Array = mock(Uint16Array);
  Int32Array = mock(Int32Array);
  Uint32Array = mock(Uint32Array);
58 59
  BigInt64Array = mock(BigInt64Array);
  BigUint64Array = mock(BigUint64Array);
60 61 62
  Float32Array = mock(Float32Array);
  Float64Array = mock(Float64Array);
})();
63

64 65 66 67 68
// Mock typed array set function and cap offset to not throw a range error.
(function() {
  // Math.min might be manipulated in test cases.
  const min = Math.min;
  const types = [
69 70 71 72 73 74 75
    Int8Array,
    Uint8Array,
    Uint8ClampedArray,
    Int16Array,
    Uint16Array,
    Int32Array,
    Uint32Array,
76 77
    BigInt64Array,
    BigUint64Array,
78 79 80
    Float32Array,
    Float64Array,
  ];
81 82 83 84 85 86 87 88
  for (const type of types) {
    const set = type.prototype.set;
    type.prototype.set = function(array, offset) {
      if (Array.isArray(array)) {
        offset = Number(offset);
        offset = min(offset, this.length - array.length);
      }
      set.call(this, array, offset);
89 90 91
    };
  }
})();