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