1// Copyright 2016 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 file is loaded before each correctness test cases and won't get 9// minimized. 10 11 12// This will be overridden in the test cases. The override can be minimized. 13var prettyPrinted = function prettyPrinted(msg) { return msg; }; 14 15// Mock Math.random. 16(function() { 17 let index = 1; 18 Math.random = function() { 19 const x = Math.sin(index++) * 10000; 20 return x - Math.floor(x); 21 } 22})(); 23 24// Mock Math.pow. Work around an optimization for -0.5. 25(function() { 26 const origMathPow = Math.pow; 27 Math.pow = function(a, b) { 28 if (b === -0.5) { 29 return 0; 30 } else { 31 return origMathPow(a, b); 32 } 33 } 34})(); 35 36 37// Mock Date. 38(function() { 39 let index = 0; 40 let mockDate = 1477662728696; 41 const mockDateNow = function() { 42 index = (index + 1) % 10; 43 mockDate = mockDate + index + 1; 44 return mockDate; 45 } 46 47 const origDate = Date; 48 const construct = Reflect.construct; 49 const constructDate = function(args) { 50 let result; 51 if (args.length) { 52 result = construct(origDate, args); 53 } else { 54 result = new origDate(mockDateNow()); 55 } 56 result.constructor = function(...args) { return constructDate(args); } 57 Object.defineProperty( 58 result, "constructor", { configurable: false, writable: false }); 59 return result; 60 } 61 62 origDate.prototype.constructor = function(...args) { 63 return constructDate(args); 64 }; 65 66 var handler = { 67 apply: function(target, thisArg, args) { 68 return constructDate(args); 69 }, 70 construct: function(target, args, newTarget) { 71 return constructDate(args); 72 }, 73 get: function(target, property, receiver) { 74 if (property == "now") { 75 return mockDateNow; 76 } 77 if (property == "prototype") { 78 return origDate.prototype; 79 } 80 }, 81 } 82 83 Date = new Proxy(Date, handler); 84})(); 85 86// Mock performance methods. 87performance.now = function() { return 1.2; }; 88performance.measureMemory = function() { return []; }; 89 90// Mock readline so that test cases don't hang. 91readline = function() { return "foo"; }; 92 93// Mock stack traces. 94Error.prepareStackTrace = function(error, structuredStackTrace) { 95 return ""; 96}; 97Object.defineProperty( 98 Error, 'prepareStackTrace', { configurable: false, writable: false }); 99 100// Mock buffer access in float typed arrays because of varying NaN patterns. 101(function() { 102 const origArrayFrom = Array.from; 103 const origArrayIsArray = Array.isArray; 104 const origFunctionPrototype = Function.prototype; 105 const origIsNaN = isNaN; 106 const origIterator = Symbol.iterator; 107 const deNaNify = function(value) { return origIsNaN(value) ? 1 : value; }; 108 const mock = function(type) { 109 110 // Remove NaN values from parameters to "set" function. 111 const set = type.prototype.set; 112 type.prototype.set = function(array, offset) { 113 if (Array.isArray(array)) { 114 array = array.map(deNaNify); 115 } 116 set.apply(this, [array, offset]); 117 }; 118 119 const handler = { 120 // Remove NaN values from parameters to constructor. 121 construct: function(target, args) { 122 for (let i = 0; i < args.length; i++) { 123 if (args[i] != null && 124 typeof args[i][origIterator] === 'function') { 125 // Consume iterators. 126 args[i] = origArrayFrom(args[i]); 127 } 128 if (origArrayIsArray(args[i])) { 129 args[i] = args[i].map(deNaNify); 130 } 131 } 132 133 const obj = new ( 134 origFunctionPrototype.bind.call(type, null, ...args)); 135 return new Proxy(obj, { 136 get: function(x, prop) { 137 if (typeof x[prop] == "function") 138 return x[prop].bind(obj); 139 return x[prop]; 140 }, 141 // Remove NaN values that get assigned. 142 set: function(target, prop, value, receiver) { 143 target[prop] = deNaNify(value); 144 return value; 145 } 146 }); 147 }, 148 }; 149 return new Proxy(type, handler); 150 } 151 152 Float32Array = mock(Float32Array); 153 Float64Array = mock(Float64Array); 154})(); 155 156// Mock buffer access via DataViews because of varying NaN patterns. 157(function() { 158 const origIsNaN = isNaN; 159 const deNaNify = function(value) { return origIsNaN(value) ? 1 : value; }; 160 const origSetFloat32 = DataView.prototype.setFloat32; 161 DataView.prototype.setFloat32 = function(offset, value, ...rest) { 162 origSetFloat32.call(this, offset, deNaNify(value), ...rest); 163 }; 164 const origSetFloat64 = DataView.prototype.setFloat64; 165 DataView.prototype.setFloat64 = function(offset, value, ...rest) { 166 origSetFloat64.call(this, offset, deNaNify(value), ...rest); 167 }; 168})(); 169 170// Mock Worker. 171(function() { 172 let index = 0; 173 // TODO(machenbach): Randomize this for each test case, but keep stable 174 // during comparison. Also data and random above. 175 const workerMessages = [ 176 undefined, 0, -1, "", "foo", 42, [], {}, [0], {"x": 0} 177 ]; 178 Worker = function(code){ 179 try { 180 print(prettyPrinted(eval(code))); 181 } catch(e) { 182 print(prettyPrinted(e)); 183 } 184 this.getMessage = function(){ 185 index = (index + 1) % 10; 186 return workerMessages[index]; 187 } 188 this.postMessage = function(msg){ 189 print(prettyPrinted(msg)); 190 } 191 }; 192})(); 193 194// Mock Realm. 195Realm.eval = function(realm, code) { return eval(code) }; 196 197// Mock the nondeterministic parts of WeakRef and FinalizationRegistry. 198WeakRef.prototype.deref = function() { }; 199FinalizationRegistry = function(callback) { }; 200FinalizationRegistry.prototype.register = function(target, holdings) { }; 201FinalizationRegistry.prototype.unregister = function(unregisterToken) { }; 202FinalizationRegistry.prototype.cleanupSome = function() { }; 203FinalizationRegistry.prototype[Symbol.toStringTag] = "FinalizationRegistry"; 204 205// Mock the nondeterministic Atomics.waitAsync. 206Atomics.waitAsync = function() { 207 // Return a mock "Promise" whose "then" function will call the callback 208 // immediately. 209 return {'value': {'then': function (f) { f(); }}}; 210} 211