• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This is intended for permanent JS behavior changes for mocking out
6// non-deterministic behavior. For temporary suppressions, please refer to
7// v8_suppressions.js.
8// This mocks only architecture specific differences. Refer to v8_mocks.js
9// for the general case.
10// This file is loaded before each correctness test cases and won't get
11// minimized.
12
13// Mock maximum typed-array buffer and limit to 1MiB. Otherwise we might
14// get range errors. We ignore those by crashing, but that reduces coverage,
15// hence, let's reduce the range-error rate.
16(function() {
17  // Math.min might be manipulated in test cases.
18  const min = Math.min;
19  const maxBytes = 1048576;
20  const mock = function(type) {
21    const maxLength = maxBytes / (type.BYTES_PER_ELEMENT || 1);
22    const handler = {
23      construct: function(target, args) {
24        if (args[0] && typeof args[0] != "object") {
25          // Length used as first argument.
26          args[0] = min(maxLength, Number(args[0]));
27        } else if (args[0] instanceof ArrayBuffer && args.length > 1) {
28          // Buffer used as first argument.
29          const buffer = args[0];
30          args[1] = Number(args[1]);
31          // Ensure offset is multiple of bytes per element.
32          args[1] = args[1] - (args[1] % type.BYTES_PER_ELEMENT);
33          // Limit offset to length of buffer.
34          args[1] = min(args[1], buffer.byteLength || 0);
35          if (args.length > 2) {
36            // If also length is given, limit it to the maximum that's possible
37            // given buffer and offset.
38            const maxBytesLeft = buffer.byteLength - args[1];
39            const maxLengthLeft = maxBytesLeft / type.BYTES_PER_ELEMENT;
40            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  Int8Array = mock(Int8Array);
52  Uint8Array = mock(Uint8Array);
53  Uint8ClampedArray = mock(Uint8ClampedArray);
54  Int16Array = mock(Int16Array);
55  Uint16Array = mock(Uint16Array);
56  Int32Array = mock(Int32Array);
57  Uint32Array = mock(Uint32Array);
58  BigInt64Array = mock(BigInt64Array);
59  BigUint64Array = mock(BigUint64Array);
60  Float32Array = mock(Float32Array);
61  Float64Array = mock(Float64Array);
62})();
63
64// Mock typed array set function and cap offset to not throw a range error.
65(function() {
66  // Math.min might be manipulated in test cases.
67  const min = Math.min;
68  const types = [
69    Int8Array,
70    Uint8Array,
71    Uint8ClampedArray,
72    Int16Array,
73    Uint16Array,
74    Int32Array,
75    Uint32Array,
76    BigInt64Array,
77    BigUint64Array,
78    Float32Array,
79    Float64Array,
80  ];
81  for (const type of types) {
82    const set = type.prototype.set;
83    type.prototype.set = function(array, offset) {
84      if (Array.isArray(array)) {
85        offset = Number(offset);
86        offset = min(offset, this.length - array.length);
87      }
88      set.call(this, array, offset);
89    };
90  }
91})();
92