OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/property-descriptor.h" | 5 #include "src/property-descriptor.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 #include "src/lookup.h" | 10 #include "src/lookup.h" |
11 #include "src/objects-inl.h" | 11 #include "src/objects-inl.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
18 // Helper function for ToPropertyDescriptor. Comments describe steps for | 18 // Helper function for ToPropertyDescriptor. Comments describe steps for |
19 // "enumerable", other properties are handled the same way. | 19 // "enumerable", other properties are handled the same way. |
20 // Returns false if an exception was thrown. | 20 // Returns false if an exception was thrown. |
21 bool GetPropertyIfPresent(Handle<Object> obj, Handle<String> name, | 21 bool GetPropertyIfPresent(Handle<JSReceiver> receiver, Handle<String> name, |
22 Handle<Object>* value) { | 22 Handle<Object>* value) { |
23 LookupIterator it(obj, name); | 23 LookupIterator it(receiver, name, receiver); |
24 // 4. Let hasEnumerable be HasProperty(Obj, "enumerable"). | 24 // 4. Let hasEnumerable be HasProperty(Obj, "enumerable"). |
25 Maybe<bool> has_property = JSReceiver::HasProperty(&it); | 25 Maybe<bool> has_property = JSReceiver::HasProperty(&it); |
26 // 5. ReturnIfAbrupt(hasEnumerable). | 26 // 5. ReturnIfAbrupt(hasEnumerable). |
27 if (has_property.IsNothing()) return false; | 27 if (has_property.IsNothing()) return false; |
28 // 6. If hasEnumerable is true, then | 28 // 6. If hasEnumerable is true, then |
29 if (has_property.FromJust() == true) { | 29 if (has_property.FromJust() == true) { |
30 // 6a. Let enum be ToBoolean(Get(Obj, "enumerable")). | 30 // 6a. Let enum be ToBoolean(Get(Obj, "enumerable")). |
31 // 6b. ReturnIfAbrupt(enum). | 31 // 6b. ReturnIfAbrupt(enum). |
32 if (!JSObject::GetProperty(&it).ToHandle(value)) return false; | 32 if (!Object::GetProperty(&it).ToHandle(value)) return false; |
33 } | 33 } |
34 return true; | 34 return true; |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 // Helper function for ToPropertyDescriptor. Handles the case of "simple" | 38 // Helper function for ToPropertyDescriptor. Handles the case of "simple" |
39 // objects: nothing on the prototype chain, just own fast data properties. | 39 // objects: nothing on the prototype chain, just own fast data properties. |
40 // Must not have observable side effects, because the slow path will restart | 40 // Must not have observable side effects, because the slow path will restart |
41 // the entire conversion! | 41 // the entire conversion! |
42 bool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<Object> obj, | 42 bool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<JSReceiver> obj, |
43 PropertyDescriptor* desc) { | 43 PropertyDescriptor* desc) { |
44 if (!obj->IsJSObject()) return false; | 44 if (!obj->IsJSObject()) return false; |
45 Map* map = Handle<JSObject>::cast(obj)->map(); | 45 Map* map = Handle<JSObject>::cast(obj)->map(); |
46 if (map->instance_type() != JS_OBJECT_TYPE) return false; | 46 if (map->instance_type() != JS_OBJECT_TYPE) return false; |
47 if (map->is_access_check_needed()) return false; | 47 if (map->is_access_check_needed()) return false; |
48 if (map->prototype() != *isolate->initial_object_prototype()) return false; | 48 if (map->prototype() != *isolate->initial_object_prototype()) return false; |
49 // During bootstrapping, the object_function_prototype_map hasn't been | 49 // During bootstrapping, the object_function_prototype_map hasn't been |
50 // set up yet. | 50 // set up yet. |
51 if (isolate->bootstrapper()->IsActive()) return false; | 51 if (isolate->bootstrapper()->IsActive()) return false; |
52 if (JSObject::cast(map->prototype())->map() != | 52 if (JSObject::cast(map->prototype())->map() != |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // 1. ReturnIfAbrupt(Obj). | 183 // 1. ReturnIfAbrupt(Obj). |
184 // 2. If Type(Obj) is not Object, throw a TypeError exception. | 184 // 2. If Type(Obj) is not Object, throw a TypeError exception. |
185 if (!obj->IsJSReceiver()) { | 185 if (!obj->IsJSReceiver()) { |
186 isolate->Throw(*isolate->factory()->NewTypeError( | 186 isolate->Throw(*isolate->factory()->NewTypeError( |
187 MessageTemplate::kPropertyDescObject, obj)); | 187 MessageTemplate::kPropertyDescObject, obj)); |
188 return false; | 188 return false; |
189 } | 189 } |
190 // 3. Let desc be a new Property Descriptor that initially has no fields. | 190 // 3. Let desc be a new Property Descriptor that initially has no fields. |
191 DCHECK(desc->is_empty()); | 191 DCHECK(desc->is_empty()); |
192 | 192 |
193 if (ToPropertyDescriptorFastPath(isolate, obj, desc)) { | 193 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(obj); |
| 194 if (ToPropertyDescriptorFastPath(isolate, receiver, desc)) { |
194 return true; | 195 return true; |
195 } | 196 } |
196 | 197 |
197 // enumerable? | 198 // enumerable? |
198 Handle<Object> enumerable; | 199 Handle<Object> enumerable; |
199 // 4 through 6b. | 200 // 4 through 6b. |
200 if (!GetPropertyIfPresent(obj, isolate->factory()->enumerable_string(), | 201 if (!GetPropertyIfPresent(receiver, isolate->factory()->enumerable_string(), |
201 &enumerable)) { | 202 &enumerable)) { |
202 return false; | 203 return false; |
203 } | 204 } |
204 // 6c. Set the [[Enumerable]] field of desc to enum. | 205 // 6c. Set the [[Enumerable]] field of desc to enum. |
205 if (!enumerable.is_null()) { | 206 if (!enumerable.is_null()) { |
206 desc->set_enumerable(enumerable->BooleanValue()); | 207 desc->set_enumerable(enumerable->BooleanValue()); |
207 } | 208 } |
208 | 209 |
209 // configurable? | 210 // configurable? |
210 Handle<Object> configurable; | 211 Handle<Object> configurable; |
211 // 7 through 9b. | 212 // 7 through 9b. |
212 if (!GetPropertyIfPresent(obj, isolate->factory()->configurable_string(), | 213 if (!GetPropertyIfPresent(receiver, isolate->factory()->configurable_string(), |
213 &configurable)) { | 214 &configurable)) { |
214 return false; | 215 return false; |
215 } | 216 } |
216 // 9c. Set the [[Configurable]] field of desc to conf. | 217 // 9c. Set the [[Configurable]] field of desc to conf. |
217 if (!configurable.is_null()) { | 218 if (!configurable.is_null()) { |
218 desc->set_configurable(configurable->BooleanValue()); | 219 desc->set_configurable(configurable->BooleanValue()); |
219 } | 220 } |
220 | 221 |
221 // value? | 222 // value? |
222 Handle<Object> value; | 223 Handle<Object> value; |
223 // 10 through 12b. | 224 // 10 through 12b. |
224 if (!GetPropertyIfPresent(obj, isolate->factory()->value_string(), &value)) { | 225 if (!GetPropertyIfPresent(receiver, isolate->factory()->value_string(), |
| 226 &value)) { |
225 return false; | 227 return false; |
226 } | 228 } |
227 // 12c. Set the [[Value]] field of desc to value. | 229 // 12c. Set the [[Value]] field of desc to value. |
228 if (!value.is_null()) desc->set_value(value); | 230 if (!value.is_null()) desc->set_value(value); |
229 | 231 |
230 // writable? | 232 // writable? |
231 Handle<Object> writable; | 233 Handle<Object> writable; |
232 // 13 through 15b. | 234 // 13 through 15b. |
233 if (!GetPropertyIfPresent(obj, isolate->factory()->writable_string(), | 235 if (!GetPropertyIfPresent(receiver, isolate->factory()->writable_string(), |
234 &writable)) { | 236 &writable)) { |
235 return false; | 237 return false; |
236 } | 238 } |
237 // 15c. Set the [[Writable]] field of desc to writable. | 239 // 15c. Set the [[Writable]] field of desc to writable. |
238 if (!writable.is_null()) desc->set_writable(writable->BooleanValue()); | 240 if (!writable.is_null()) desc->set_writable(writable->BooleanValue()); |
239 | 241 |
240 // getter? | 242 // getter? |
241 Handle<Object> getter; | 243 Handle<Object> getter; |
242 // 16 through 18b. | 244 // 16 through 18b. |
243 if (!GetPropertyIfPresent(obj, isolate->factory()->get_string(), &getter)) { | 245 if (!GetPropertyIfPresent(receiver, isolate->factory()->get_string(), |
| 246 &getter)) { |
244 return false; | 247 return false; |
245 } | 248 } |
246 if (!getter.is_null()) { | 249 if (!getter.is_null()) { |
247 // 18c. If IsCallable(getter) is false and getter is not undefined, | 250 // 18c. If IsCallable(getter) is false and getter is not undefined, |
248 // throw a TypeError exception. | 251 // throw a TypeError exception. |
249 if (!getter->IsCallable() && !getter->IsUndefined()) { | 252 if (!getter->IsCallable() && !getter->IsUndefined()) { |
250 isolate->Throw(*isolate->factory()->NewTypeError( | 253 isolate->Throw(*isolate->factory()->NewTypeError( |
251 MessageTemplate::kObjectGetterCallable, getter)); | 254 MessageTemplate::kObjectGetterCallable, getter)); |
252 return false; | 255 return false; |
253 } | 256 } |
254 // 18d. Set the [[Get]] field of desc to getter. | 257 // 18d. Set the [[Get]] field of desc to getter. |
255 desc->set_get(getter); | 258 desc->set_get(getter); |
256 } | 259 } |
257 // setter? | 260 // setter? |
258 Handle<Object> setter; | 261 Handle<Object> setter; |
259 // 19 through 21b. | 262 // 19 through 21b. |
260 if (!GetPropertyIfPresent(obj, isolate->factory()->set_string(), &setter)) { | 263 if (!GetPropertyIfPresent(receiver, isolate->factory()->set_string(), |
| 264 &setter)) { |
261 return false; | 265 return false; |
262 } | 266 } |
263 if (!setter.is_null()) { | 267 if (!setter.is_null()) { |
264 // 21c. If IsCallable(setter) is false and setter is not undefined, | 268 // 21c. If IsCallable(setter) is false and setter is not undefined, |
265 // throw a TypeError exception. | 269 // throw a TypeError exception. |
266 if (!setter->IsCallable() && !setter->IsUndefined()) { | 270 if (!setter->IsCallable() && !setter->IsUndefined()) { |
267 isolate->Throw(*isolate->factory()->NewTypeError( | 271 isolate->Throw(*isolate->factory()->NewTypeError( |
268 MessageTemplate::kObjectSetterCallable, setter)); | 272 MessageTemplate::kObjectSetterCallable, setter)); |
269 return false; | 273 return false; |
270 } | 274 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 // Desc.[[Enumerable]] to like.[[Enumerable]]. | 329 // Desc.[[Enumerable]] to like.[[Enumerable]]. |
326 if (!desc->has_enumerable()) desc->set_enumerable(false); | 330 if (!desc->has_enumerable()) desc->set_enumerable(false); |
327 // 7. If Desc does not have a [[Configurable]] field, set | 331 // 7. If Desc does not have a [[Configurable]] field, set |
328 // Desc.[[Configurable]] to like.[[Configurable]]. | 332 // Desc.[[Configurable]] to like.[[Configurable]]. |
329 if (!desc->has_configurable()) desc->set_configurable(false); | 333 if (!desc->has_configurable()) desc->set_configurable(false); |
330 // 8. Return Desc. | 334 // 8. Return Desc. |
331 } | 335 } |
332 | 336 |
333 } // namespace internal | 337 } // namespace internal |
334 } // namespace v8 | 338 } // namespace v8 |
OLD | NEW |