1 // Copyright 2015 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 // Flags: --strong-mode --allow-natives-syntax 6 7 function getSloppyArguments() { 8 return arguments; 9 } 10 11 function getObjects() { 12 "use strict"; 13 return [ 14 {}, 15 Object(""), 16 [], 17 (function(){}), 18 (class Foo {}), 19 getSloppyArguments(), 20 arguments, 21 new Date(), 22 ]; 23 } 24 25 // TODO(conradw): add tests for non-inheritance once semantics are implemented. 26 function getNonInheritingObjects() { 27 "use strong"; 28 return [ 29 Object(""), 30 [], 31 // TODO(conradw): uncomment and correct test once Object.defineProperty is 32 // fixed. 33 // new Uint32Array(0) 34 ]; 35 } 36 37 function readFromObjectElementSloppy(o) { 38 return o[0]; 39 } 40 41 function readFromObjectElementSparseSloppy(o) { 42 return o[100000]; 43 } 44 45 function readFromObjectElementNonSmiSloppy(o) { 46 return o[3000000000]; 47 } 48 49 function readFromObjectNonIndexSloppy(o) { 50 return o[5000000000]; 51 } 52 53 function readFromObjectElementVarSloppy(o) { 54 var a = 0; 55 return o[a]; 56 } 57 58 function readFromObjectElementSparseVarSloppy(o) { 59 var a = 100000; 60 return o[a]; 61 } 62 63 function readFromObjectElementNonSmiVarSloppy(o) { 64 var a = 3000000000; 65 return o[a]; 66 } 67 68 function readFromObjectNonIndexVarSloppy(o) { 69 var a = 5000000000; 70 return o[a]; 71 } 72 73 function readFromObjectElementStrong(o) { 74 "use strong"; 75 return o[0]; 76 } 77 78 function readFromObjectElementSparseStrong(o) { 79 "use strong"; 80 return o[100000]; 81 } 82 83 function readFromObjectElementNonSmiStrong(o) { 84 "use strong"; 85 return o[3000000000]; 86 } 87 88 function readFromObjectNonIndexStrong(o) { 89 "use strong"; 90 return o[5000000000]; 91 } 92 93 function readFromObjectElementLetStrong(o) { 94 "use strong"; 95 let a = 0; 96 return o[a]; 97 } 98 99 function readFromObjectElementSparseLetStrong(o) { 100 "use strong"; 101 let a = 100000; 102 return o[a]; 103 } 104 105 function readFromObjectElementNonSmiLetStrong(o) { 106 "use strong"; 107 let a = 3000000000; 108 return o[a]; 109 } 110 111 function readFromObjectNonIndexLetStrong(o) { 112 "use strong"; 113 let a = 5000000000; 114 return o[a]; 115 } 116 117 function getDescs(x) { 118 return [ 119 {value: x}, 120 {configurable: true, enumerable: true, writable: true, value: x}, 121 {configurable: true, enumerable: true, get: (function() {return x}) }, 122 ]; 123 } 124 125 function assertStrongSemantics(func, object) { 126 %DeoptimizeFunction(func); 127 %ClearFunctionTypeFeedback(func); 128 assertThrows(function(){func(object)}, TypeError); 129 assertThrows(function(){func(object)}, TypeError); 130 assertThrows(function(){func(object)}, TypeError); 131 %OptimizeFunctionOnNextCall(func); 132 assertThrows(function(){func(object)}, TypeError); 133 %DeoptimizeFunction(func); 134 assertThrows(function(){func(object)}, TypeError); 135 } 136 137 function assertSloppySemantics(func, object) { 138 %DeoptimizeFunction(func); 139 %ClearFunctionTypeFeedback(func); 140 assertDoesNotThrow(function(){func(object)}); 141 assertDoesNotThrow(function(){func(object)}); 142 assertDoesNotThrow(function(){func(object)}); 143 %OptimizeFunctionOnNextCall(func); 144 assertDoesNotThrow(function(){func(object)}); 145 %DeoptimizeFunction(func); 146 assertDoesNotThrow(function(){func(object)}); 147 } 148 149 (function () { 150 "use strict"; 151 152 let goodKeys = [ 153 "0", 154 "100000", 155 "3000000000", 156 "5000000000" 157 ] 158 159 let badKeys = [ 160 "bar", 161 "1", 162 "100001", 163 "3000000001", 164 "5000000001" 165 ]; 166 167 let values = [ 168 "string", 169 1, 170 100001, 171 30000000001, 172 50000000001, 173 NaN, 174 {}, 175 undefined 176 ]; 177 178 let badAccessorDescs = [ 179 { set: (function(){}) }, 180 { configurable: true, enumerable: true, set: (function(){}) } 181 ]; 182 183 let readSloppy = [ 184 readFromObjectElementSloppy, 185 readFromObjectElementSparseSloppy, 186 readFromObjectElementNonSmiSloppy, 187 readFromObjectNonIndexSloppy, 188 readFromObjectElementVarSloppy, 189 readFromObjectElementSparseVarSloppy, 190 readFromObjectElementNonSmiVarSloppy, 191 readFromObjectNonIndexVarSloppy 192 ]; 193 194 let readStrong = [ 195 readFromObjectElementStrong, 196 readFromObjectElementSparseStrong, 197 readFromObjectElementNonSmiStrong, 198 readFromObjectNonIndexStrong, 199 readFromObjectElementLetStrong, 200 readFromObjectElementSparseLetStrong, 201 readFromObjectElementNonSmiLetStrong, 202 readFromObjectNonIndexLetStrong 203 ]; 204 205 let dummyProto = {}; 206 for (let key of goodKeys) { 207 Object.defineProperty(dummyProto, key, { value: undefined }); 208 } 209 210 // After altering the backing store, accessing a missing property should still 211 // throw. 212 for (let key of badKeys) { 213 for (let value of values) { 214 for (let desc of getDescs(value)) { 215 let objects = getObjects(); 216 let nonInheritingObjects = getNonInheritingObjects(); 217 for (let object of objects.concat(nonInheritingObjects)) { 218 Object.defineProperty(object, key, desc); 219 for (let func of readStrong) { 220 assertStrongSemantics(func, object); 221 } 222 for (let func of readSloppy) { 223 assertSloppySemantics(func, object); 224 } 225 } 226 for (let object of objects) { 227 // Accessing a property which is on the prototype chain of the object 228 // should not throw. 229 object.__proto__ = dummyProto; 230 for (let key of goodKeys) { 231 for (let func of readStrong.concat(readSloppy)) { 232 assertSloppySemantics(func, object); 233 } 234 } 235 } 236 } 237 } 238 } 239 })(); 240