blob: 4007b7db6163325b53dc5472ceb0f3d03f16b7cd [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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})();