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 new Uint32Array(0) 23 ]; 24} 25 26function readFromObjectSloppy(o) { 27 return o.foo; 28} 29 30function readFromObjectKeyedSloppy(o) { 31 return o["foo"]; 32} 33 34function readFromObjectKeyedVarSloppy(o) { 35 var a = "foo"; 36 return o[a]; 37} 38 39function readFromObjectKeyedComputedSloppy(o) { 40 var a = "o"; 41 return o["fo" + a]; 42} 43 44function readFromObjectStrong(o) { 45 "use strong"; 46 return o.foo; 47} 48 49function readFromObjectKeyedStrong(o) { 50 "use strong"; 51 return o["foo"]; 52} 53 54function readFromObjectKeyedLetStrong(o) { 55 "use strong"; 56 let a = "foo"; 57 return o[a]; 58} 59 60function readFromObjectKeyedComputedStrong(o) { 61 "use strong"; 62 let a = "o"; 63 return o["fo" + a]; 64} 65 66function getDescs(x) { 67 return [ 68 {value: x}, 69 {configurable: true, enumerable: true, writable: true, value: x}, 70 {configurable: true, enumerable: true, get: (function() {return x}) }, 71 ]; 72} 73 74function assertStrongSemantics(func, object) { 75 %DeoptimizeFunction(func); 76 %ClearFunctionTypeFeedback(func); 77 assertThrows(function(){func(object)}, TypeError); 78 assertThrows(function(){func(object)}, TypeError); 79 assertThrows(function(){func(object)}, TypeError); 80 %OptimizeFunctionOnNextCall(func); 81 assertThrows(function(){func(object)}, TypeError); 82 %DeoptimizeFunction(func); 83 assertThrows(function(){func(object)}, TypeError); 84} 85 86function assertSloppySemantics(func, object) { 87 %DeoptimizeFunction(func); 88 %ClearFunctionTypeFeedback(func); 89 assertDoesNotThrow(function(){func(object)}); 90 assertDoesNotThrow(function(){func(object)}); 91 assertDoesNotThrow(function(){func(object)}); 92 %OptimizeFunctionOnNextCall(func); 93 assertDoesNotThrow(function(){func(object)}); 94 %DeoptimizeFunction(func); 95 assertDoesNotThrow(function(){func(object)}); 96} 97 98(function () { 99 "use strict"; 100 101 let goodKeys = [ 102 "foo" 103 ] 104 105 let badKeys = [ 106 "bar", 107 "1", 108 "100001", 109 "3000000001", 110 "5000000001" 111 ]; 112 113 let values = [ 114 "string", 115 1, 116 100001, 117 30000000001, 118 50000000001, 119 NaN, 120 {}, 121 undefined 122 ]; 123 124 let literals = [0, NaN, true, "string"]; 125 126 let badAccessorDescs = [ 127 { set: (function(){}) }, 128 { configurable: true, enumerable: true, set: (function(){}) } 129 ]; 130 131 let readSloppy = [ 132 readFromObjectSloppy, 133 readFromObjectKeyedSloppy, 134 readFromObjectKeyedVarSloppy, 135 readFromObjectKeyedComputedSloppy 136 ]; 137 138 let readStrong = [ 139 readFromObjectStrong, 140 readFromObjectKeyedStrong, 141 readFromObjectKeyedLetStrong, 142 readFromObjectKeyedComputedStrong 143 ]; 144 145 let dummyProto = {}; 146 for (let key of goodKeys) { 147 Object.defineProperty(dummyProto, key, { value: undefined }); 148 } 149 150 let dummyAccessorProto = {}; 151 for (let key of goodKeys) { 152 Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) }) 153 } 154 155 // Attempting to access a property on an object with no defined properties 156 // should throw. 157 for (let object of getObjects().concat(literals)) { 158 for (let func of readStrong) { 159 assertStrongSemantics(func, object); 160 } 161 for (let func of readSloppy) { 162 assertSloppySemantics(func, object); 163 } 164 } 165 for (let object of getObjects()) { 166 // Accessing a property which is on the prototype chain of the object should 167 // not throw. 168 object.__proto__ = dummyProto; 169 for (let key of goodKeys) { 170 for (let func of readStrong.concat(readSloppy)) { 171 assertSloppySemantics(func, object); 172 } 173 } 174 } 175 // Properties with accessor descriptors missing 'get' should throw on access. 176 for (let desc of badAccessorDescs) { 177 for (let key of goodKeys) { 178 for (let object of getObjects()) { 179 Object.defineProperty(object, key, desc); 180 for (let func of readStrong) { 181 assertStrongSemantics(func, object); 182 } 183 for (let func of readSloppy) { 184 assertSloppySemantics(func, object); 185 } 186 } 187 } 188 } 189 // The same behaviour should be expected for bad accessor properties on the 190 // prototype chain. 191 for (let object of getObjects()) { 192 object.__proto__ = dummyAccessorProto; 193 for (let func of readStrong) { 194 assertStrongSemantics(func, object); 195 } 196 for (let func of readSloppy) { 197 assertSloppySemantics(func, object); 198 } 199 } 200 assertThrows(function(){"use strong"; typeof ({}).foo;}, TypeError); 201 assertThrows( 202 function(){"use strong"; typeof ({}).foo === "undefined"}, TypeError); 203})(); 204