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 new Uint32Array(0) | |
23 ]; | |
24 } | |
25 | |
26 function readFromObjectSloppy(o) { | |
27 return o.foo; | |
28 } | |
29 | |
30 function readFromObjectKeyedSloppy(o) { | |
31 return o["foo"]; | |
32 } | |
33 | |
34 function readFromObjectKeyedVarSloppy(o) { | |
35 var a = "foo"; | |
36 return o[a]; | |
37 } | |
38 | |
39 function readFromObjectKeyedComputedSloppy(o) { | |
40 var a = "o"; | |
41 return o["fo" + a]; | |
42 } | |
43 | |
44 function readFromObjectStrong(o) { | |
45 "use strong"; | |
46 return o.foo; | |
47 } | |
48 | |
49 function readFromObjectKeyedStrong(o) { | |
50 "use strong"; | |
51 return o["foo"]; | |
52 } | |
53 | |
54 function readFromObjectKeyedLetStrong(o) { | |
55 "use strong"; | |
56 let a = "foo"; | |
57 return o[a]; | |
58 } | |
59 | |
60 function readFromObjectKeyedComputedStrong(o) { | |
61 "use strong"; | |
62 let a = "o"; | |
63 return o["fo" + a]; | |
64 } | |
65 | |
66 function 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 | |
74 function 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 | |
86 function 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 })(); | |
OLD | NEW |