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