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 7function getSloppyArguments() { 8 return arguments; 9} 10 11function 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. 26function getNonInheritingObjects() { 27 "use strong"; 28 return [ 29 Object(""), 30 [], 31 new Uint32Array(0) 32 ]; 33} 34 35function readFromObjectElementSloppy(o) { 36 return o[0]; 37} 38 39function readFromObjectElementSparseSloppy(o) { 40 return o[100000]; 41} 42 43function readFromObjectElementNonSmiSloppy(o) { 44 return o[3000000000]; 45} 46 47function readFromObjectNonIndexSloppy(o) { 48 return o[5000000000]; 49} 50 51function readFromObjectElementVarSloppy(o) { 52 var a = 0; 53 return o[a]; 54} 55 56function readFromObjectElementSparseVarSloppy(o) { 57 var a = 100000; 58 return o[a]; 59} 60 61function readFromObjectElementNonSmiVarSloppy(o) { 62 var a = 3000000000; 63 return o[a]; 64} 65 66function readFromObjectNonIndexVarSloppy(o) { 67 var a = 5000000000; 68 return o[a]; 69} 70 71function readFromObjectElementStrong(o) { 72 "use strong"; 73 return o[0]; 74} 75 76function readFromObjectElementSparseStrong(o) { 77 "use strong"; 78 return o[100000]; 79} 80 81function readFromObjectElementNonSmiStrong(o) { 82 "use strong"; 83 return o[3000000000]; 84} 85 86function readFromObjectNonIndexStrong(o) { 87 "use strong"; 88 return o[5000000000]; 89} 90 91function readFromObjectElementLetStrong(o) { 92 "use strong"; 93 let a = 0; 94 return o[a]; 95} 96 97function readFromObjectElementSparseLetStrong(o) { 98 "use strong"; 99 let a = 100000; 100 return o[a]; 101} 102 103function readFromObjectElementNonSmiLetStrong(o) { 104 "use strong"; 105 let a = 3000000000; 106 return o[a]; 107} 108 109function readFromObjectNonIndexLetStrong(o) { 110 "use strong"; 111 let a = 5000000000; 112 return o[a]; 113} 114 115function getDescs(x) { 116 return [ 117 {value: x}, 118 {configurable: true, enumerable: true, writable: true, value: x}, 119 {configurable: true, enumerable: true, get: (function() {return x}) }, 120 ]; 121} 122 123function assertStrongSemantics(func, object) { 124 %DeoptimizeFunction(func); 125 %ClearFunctionTypeFeedback(func); 126 assertThrows(function(){func(object)}, TypeError); 127 assertThrows(function(){func(object)}, TypeError); 128 assertThrows(function(){func(object)}, TypeError); 129 %OptimizeFunctionOnNextCall(func); 130 assertThrows(function(){func(object)}, TypeError); 131 %DeoptimizeFunction(func); 132 assertThrows(function(){func(object)}, TypeError); 133} 134 135function assertSloppySemantics(func, object) { 136 %DeoptimizeFunction(func); 137 %ClearFunctionTypeFeedback(func); 138 assertDoesNotThrow(function(){func(object)}); 139 assertDoesNotThrow(function(){func(object)}); 140 assertDoesNotThrow(function(){func(object)}); 141 %OptimizeFunctionOnNextCall(func); 142 assertDoesNotThrow(function(){func(object)}); 143 %DeoptimizeFunction(func); 144 assertDoesNotThrow(function(){func(object)}); 145} 146 147(function () { 148 "use strict"; 149 150 let goodKeys = [ 151 "0", 152 "100000", 153 "3000000000", 154 "5000000000" 155 ] 156 157 let badKeys = [ 158 "bar", 159 "1", 160 "100001", 161 "3000000001", 162 "5000000001" 163 ]; 164 165 let values = [ 166 "string", 167 1, 168 100001, 169 30000000001, 170 50000000001, 171 NaN, 172 {}, 173 undefined 174 ]; 175 176 let literals = [0, NaN, true, ""]; 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 let dummyAccessorProto = {}; 211 for (let key of goodKeys) { 212 Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) }) 213 } 214 215 // String literals/objects should not throw on character index access 216 assertDoesNotThrow(function() {"use strong"; return "string"[0]; }); 217 assertDoesNotThrow(function() {"use strong"; return Object("string")[0]; }); 218 219 // Attempting to access a property on an object with no defined properties 220 // should throw. 221 for (let object of getObjects().concat(getNonInheritingObjects(), literals)) { 222 for (let func of readStrong) { 223 assertStrongSemantics(func, object); 224 } 225 for (let func of readSloppy) { 226 assertSloppySemantics(func, object); 227 } 228 } 229 for (let object of getObjects()) { 230 // Accessing a property which is on the prototype chain of the object should 231 // not throw. 232 object.__proto__ = dummyProto; 233 for (let key of goodKeys) { 234 for (let func of readStrong.concat(readSloppy)) { 235 assertSloppySemantics(func, object); 236 } 237 } 238 } 239 // Properties with accessor descriptors missing 'get' should throw on access. 240 for (let desc of badAccessorDescs) { 241 for (let key of goodKeys) { 242 for (let object of getObjects()) { 243 Object.defineProperty(object, key, desc); 244 for (let func of readStrong) { 245 assertStrongSemantics(func, object); 246 } 247 for (let func of readSloppy) { 248 assertSloppySemantics(func, object); 249 } 250 } 251 } 252 } 253 // The same behaviour should be expected for bad accessor properties on the 254 // prototype chain. 255 for (let object of getObjects()) { 256 object.__proto__ = dummyAccessorProto; 257 for (let func of readStrong) { 258 assertStrongSemantics(func, object); 259 } 260 for (let func of readSloppy) { 261 assertSloppySemantics(func, object); 262 } 263 } 264 assertThrows(function(){"use strong"; typeof ({})[1];}, TypeError); 265 assertThrows( 266 function(){"use strong"; typeof ({})[1] === "undefined"}, TypeError); 267})(); 268