OLD | NEW |
| (Empty) |
1 // Copyright 2011 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | |
28 // Flags: --allow-natives-syntax --harmony-proxies --es5_readonly | |
29 | |
30 // Different ways to create an object. | |
31 | |
32 function CreateFromLiteral() { | |
33 return {}; | |
34 } | |
35 | |
36 function CreateFromObject() { | |
37 return new Object; | |
38 } | |
39 | |
40 function CreateDefault() { | |
41 return Object.create(Object.prototype); | |
42 } | |
43 | |
44 function CreateFromConstructor(proto) { | |
45 function C() {} | |
46 (new C).b = 9; // Make sure that we can have an in-object property. | |
47 C.prototype = proto; | |
48 return function() { return new C; } | |
49 } | |
50 | |
51 function CreateFromApi(proto) { | |
52 return function() { return Object.create(proto); } | |
53 } | |
54 | |
55 function CreateWithProperty(proto) { | |
56 function C() { this.a = -100; } | |
57 C.prototype = proto; | |
58 return function() { return new C; } | |
59 } | |
60 | |
61 var bases = [CreateFromLiteral, CreateFromObject, CreateDefault]; | |
62 var inherits = [CreateFromConstructor, CreateFromApi, CreateWithProperty]; | |
63 var constructs = [CreateFromConstructor, CreateFromApi]; | |
64 | |
65 function TestAllCreates(f) { | |
66 // The depth of the prototype chain up the. | |
67 for (var depth = 0; depth < 3; ++depth) { | |
68 // Introduce readonly-ness this far up the chain. | |
69 for (var up = 0; up <= depth; ++up) { | |
70 // Try different construction methods. | |
71 for (var k = 0; k < constructs.length; ++k) { | |
72 // Construct a fresh prototype chain from above functions. | |
73 for (var i = 0; i < bases.length; ++i) { | |
74 var p = bases[i](); | |
75 // There may be a preexisting property under the insertion point... | |
76 for (var j = 0; j < depth - up; ++j) { | |
77 p = inherits[Math.floor(inherits.length * Math.random())](p)(); | |
78 } | |
79 // ...but not above it. | |
80 for (var j = 0; j < up; ++j) { | |
81 p = constructs[Math.floor(constructs.length * Math.random())](p)(); | |
82 } | |
83 // Create a fresh constructor. | |
84 var c = constructs[k](p); | |
85 f(function() { | |
86 var o = c(); | |
87 o.up = o; | |
88 for (var j = 0; j < up; ++j) o.up = Object.getPrototypeOf(o.up); | |
89 return o; | |
90 }) | |
91 } | |
92 } | |
93 } | |
94 } | |
95 } | |
96 | |
97 | |
98 // Different ways to make a property read-only. | |
99 | |
100 function ReadonlyByNonwritableDataProperty(o, name) { | |
101 Object.defineProperty(o, name, {value: -41, writable: false}); | |
102 } | |
103 | |
104 function ReadonlyByAccessorPropertyWithoutSetter(o, name) { | |
105 Object.defineProperty(o, name, {get: function() { return -42; }}); | |
106 } | |
107 | |
108 function ReadonlyByGetter(o, name) { | |
109 o.__defineGetter__("a", function() { return -43; }); | |
110 } | |
111 | |
112 function ReadonlyByFreeze(o, name) { | |
113 o[name] = -44; | |
114 Object.freeze(o); | |
115 } | |
116 | |
117 function ReadonlyByProto(o, name) { | |
118 var p = Object.create(o.__proto__); | |
119 Object.defineProperty(p, name, {value: -45, writable: false}); | |
120 o.__proto__ = p; | |
121 } | |
122 | |
123 function ReadonlyByProxy(o, name) { | |
124 var p = Proxy.create({ | |
125 getPropertyDescriptor: function() { | |
126 return {value: -46, writable: false, configurable: true}; | |
127 } | |
128 }); | |
129 o.__proto__ = p; | |
130 } | |
131 | |
132 var readonlys = [ | |
133 ReadonlyByNonwritableDataProperty, ReadonlyByAccessorPropertyWithoutSetter, | |
134 ReadonlyByGetter, ReadonlyByFreeze, ReadonlyByProto, ReadonlyByProxy | |
135 ] | |
136 | |
137 function TestAllReadonlys(f) { | |
138 // Provide various methods to making a property read-only. | |
139 for (var i = 0; i < readonlys.length; ++i) { | |
140 print(" readonly =", i) | |
141 f(readonlys[i]); | |
142 } | |
143 } | |
144 | |
145 | |
146 // Different use scenarios. | |
147 | |
148 function Assign(o, x) { | |
149 o.a = x; | |
150 } | |
151 | |
152 function AssignStrict(o, x) { | |
153 "use strict"; | |
154 o.a = x; | |
155 } | |
156 | |
157 function TestAllModes(f) { | |
158 for (var strict = 0; strict < 2; ++strict) { | |
159 print(" strict =", strict); | |
160 f(strict); | |
161 } | |
162 } | |
163 | |
164 function TestAllScenarios(f) { | |
165 for (var t = 0; t < 100; t = 2*t + 1) { | |
166 print("t =", t) | |
167 f(function(strict, create, readonly) { | |
168 // Make sure that the assignments are monomorphic. | |
169 %DeoptimizeFunction(Assign); | |
170 %DeoptimizeFunction(AssignStrict); | |
171 %ClearFunctionTypeFeedback(Assign); | |
172 %ClearFunctionTypeFeedback(AssignStrict); | |
173 for (var i = 0; i < t; ++i) { | |
174 var o = create(); | |
175 assertFalse("a" in o && !("a" in o.__proto__)); | |
176 if (strict === 0) | |
177 Assign(o, i); | |
178 else | |
179 AssignStrict(o, i); | |
180 assertEquals(i, o.a); | |
181 } | |
182 %OptimizeFunctionOnNextCall(Assign); | |
183 %OptimizeFunctionOnNextCall(AssignStrict); | |
184 var o = create(); | |
185 assertFalse("a" in o && !("a" in o.__proto__)); | |
186 readonly(o.up, "a"); | |
187 assertTrue("a" in o); | |
188 if (strict === 0) | |
189 Assign(o, t + 1); | |
190 else | |
191 assertThrows(function() { AssignStrict(o, t + 1) }, TypeError); | |
192 assertTrue(o.a < 0); | |
193 }); | |
194 } | |
195 } | |
196 | |
197 | |
198 // Runner. | |
199 | |
200 TestAllScenarios(function(scenario) { | |
201 TestAllModes(function(strict) { | |
202 TestAllReadonlys(function(readonly) { | |
203 TestAllCreates(function(create) { | |
204 scenario(strict, create, readonly); | |
205 }); | |
206 }); | |
207 }); | |
208 }); | |
209 | |
210 | |
211 // Extra test forcing bailout. | |
212 | |
213 function Assign2(o, x) { o.a = x } | |
214 | |
215 (function() { | |
216 var p = CreateFromConstructor(Object.prototype)(); | |
217 var c = CreateFromConstructor(p); | |
218 for (var i = 0; i < 3; ++i) { | |
219 var o = c(); | |
220 Assign2(o, i); | |
221 assertEquals(i, o.a); | |
222 } | |
223 %OptimizeFunctionOnNextCall(Assign2); | |
224 ReadonlyByNonwritableDataProperty(p, "a"); | |
225 var o = c(); | |
226 Assign2(o, 0); | |
227 assertTrue(o.a < 0); | |
228 })(); | |
OLD | NEW |