OLD | NEW |
| (Empty) |
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 new Uint32Array(0) | |
32 ]; | |
33 } | |
34 | |
35 function readFromObjectElementSloppy(o) { | |
36 return o[0]; | |
37 } | |
38 | |
39 function readFromObjectElementSparseSloppy(o) { | |
40 return o[100000]; | |
41 } | |
42 | |
43 function readFromObjectElementNonSmiSloppy(o) { | |
44 return o[3000000000]; | |
45 } | |
46 | |
47 function readFromObjectNonIndexSloppy(o) { | |
48 return o[5000000000]; | |
49 } | |
50 | |
51 function readFromObjectElementVarSloppy(o) { | |
52 var a = 0; | |
53 return o[a]; | |
54 } | |
55 | |
56 function readFromObjectElementSparseVarSloppy(o) { | |
57 var a = 100000; | |
58 return o[a]; | |
59 } | |
60 | |
61 function readFromObjectElementNonSmiVarSloppy(o) { | |
62 var a = 3000000000; | |
63 return o[a]; | |
64 } | |
65 | |
66 function readFromObjectNonIndexVarSloppy(o) { | |
67 var a = 5000000000; | |
68 return o[a]; | |
69 } | |
70 | |
71 function readFromObjectElementStrong(o) { | |
72 "use strong"; | |
73 return o[0]; | |
74 } | |
75 | |
76 function readFromObjectElementSparseStrong(o) { | |
77 "use strong"; | |
78 return o[100000]; | |
79 } | |
80 | |
81 function readFromObjectElementNonSmiStrong(o) { | |
82 "use strong"; | |
83 return o[3000000000]; | |
84 } | |
85 | |
86 function readFromObjectNonIndexStrong(o) { | |
87 "use strong"; | |
88 return o[5000000000]; | |
89 } | |
90 | |
91 function readFromObjectElementLetStrong(o) { | |
92 "use strong"; | |
93 let a = 0; | |
94 return o[a]; | |
95 } | |
96 | |
97 function readFromObjectElementSparseLetStrong(o) { | |
98 "use strong"; | |
99 let a = 100000; | |
100 return o[a]; | |
101 } | |
102 | |
103 function readFromObjectElementNonSmiLetStrong(o) { | |
104 "use strong"; | |
105 let a = 3000000000; | |
106 return o[a]; | |
107 } | |
108 | |
109 function readFromObjectNonIndexLetStrong(o) { | |
110 "use strong"; | |
111 let a = 5000000000; | |
112 return o[a]; | |
113 } | |
114 | |
115 function 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 | |
123 function 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 | |
135 function 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 })(); | |
OLD | NEW |