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