| 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 |