5 #include "src/property-descriptor.h" 7 #include "src/bootstrapper.h" 8 #include "src/heap/factory.h" 9 #include "src/isolate-inl.h" 10 #include "src/lookup.h" 11 #include "src/objects-inl.h" 12 #include "src/objects/property-descriptor-object-inl.h" 22 bool GetPropertyIfPresent(Handle<JSReceiver> receiver, Handle<String> name,
23 Handle<Object>* value) {
24 LookupIterator it(receiver, name, receiver);
26 Maybe<bool> has_property = JSReceiver::HasProperty(&it);
28 if (has_property.IsNothing())
return false;
30 if (has_property.FromJust() ==
true) {
33 if (!Object::GetProperty(&it).ToHandle(value))
return false;
43 bool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<JSReceiver> obj,
44 PropertyDescriptor* desc) {
45 if (!obj->IsJSObject())
return false;
46 Map map = Handle<JSObject>::cast(obj)->map();
47 if (map->instance_type() != JS_OBJECT_TYPE)
return false;
48 if (map->is_access_check_needed())
return false;
49 if (map->prototype() != *isolate->initial_object_prototype())
return false;
52 if (isolate->bootstrapper()->IsActive())
return false;
53 if (JSObject::cast(map->prototype())->map() !=
54 isolate->native_context()->object_function_prototype_map()) {
58 if (map->is_dictionary_map())
return false;
59 Handle<DescriptorArray> descs =
60 Handle<DescriptorArray>(map->instance_descriptors(), isolate);
61 for (
int i = 0;
i < map->NumberOfOwnDescriptors();
i++) {
62 PropertyDetails details = descs->GetDetails(
i);
63 Name key = descs->GetKey(
i);
65 if (details.location() == kField) {
66 if (details.kind() == kData) {
67 value = JSObject::FastPropertyAt(Handle<JSObject>::cast(obj),
68 details.representation(),
69 FieldIndex::ForDescriptor(map,
i));
71 DCHECK_EQ(kAccessor, details.kind());
77 DCHECK_EQ(kDescriptor, details.location());
78 if (details.kind() == kData) {
79 value = handle(descs->GetStrongValue(
i), isolate);
81 DCHECK_EQ(kAccessor, details.kind());
86 ReadOnlyRoots roots(isolate);
87 if (key == roots.enumerable_string()) {
88 desc->set_enumerable(value->BooleanValue(isolate));
89 }
else if (key == roots.configurable_string()) {
90 desc->set_configurable(value->BooleanValue(isolate));
91 }
else if (key == roots.value_string()) {
92 desc->set_value(value);
93 }
else if (key == roots.writable_string()) {
94 desc->set_writable(value->BooleanValue(isolate));
95 }
else if (key == roots.get_string()) {
97 if (!value->IsCallable())
return false;
99 }
else if (key == roots.set_string()) {
101 if (!value->IsCallable())
return false;
102 desc->set_set(value);
105 if ((desc->has_get() || desc->has_set()) &&
106 (desc->has_value() || desc->has_writable())) {
113 void CreateDataProperty(Handle<JSObject>
object, Handle<String> name,
114 Handle<Object> value) {
115 LookupIterator it(
object, name,
object, LookupIterator::OWN_SKIP_INTERCEPTOR);
116 Maybe<bool> result = JSObject::CreateDataProperty(&it, value);
117 CHECK(result.IsJust() && result.FromJust());
124 Handle<Object> PropertyDescriptor::ToObject(Isolate* isolate) {
125 DCHECK(!(PropertyDescriptor::IsAccessorDescriptor(
this) &&
126 PropertyDescriptor::IsDataDescriptor(
this)));
127 Factory* factory = isolate->factory();
128 if (IsRegularAccessorProperty()) {
130 Handle<JSObject> result = factory->NewJSObjectFromMap(
131 isolate->accessor_property_descriptor_map());
132 result->InObjectPropertyAtPut(JSAccessorPropertyDescriptor::kGetIndex,
134 result->InObjectPropertyAtPut(JSAccessorPropertyDescriptor::kSetIndex,
136 result->InObjectPropertyAtPut(
137 JSAccessorPropertyDescriptor::kEnumerableIndex,
138 isolate->heap()->ToBoolean(enumerable()));
139 result->InObjectPropertyAtPut(
140 JSAccessorPropertyDescriptor::kConfigurableIndex,
141 isolate->heap()->ToBoolean(configurable()));
144 if (IsRegularDataProperty()) {
146 Handle<JSObject> result =
147 factory->NewJSObjectFromMap(isolate->data_property_descriptor_map());
148 result->InObjectPropertyAtPut(JSDataPropertyDescriptor::kValueIndex,
150 result->InObjectPropertyAtPut(JSDataPropertyDescriptor::kWritableIndex,
151 isolate->heap()->ToBoolean(writable()));
152 result->InObjectPropertyAtPut(JSDataPropertyDescriptor::kEnumerableIndex,
153 isolate->heap()->ToBoolean(enumerable()));
154 result->InObjectPropertyAtPut(JSDataPropertyDescriptor::kConfigurableIndex,
155 isolate->heap()->ToBoolean(configurable()));
158 Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
160 CreateDataProperty(result, factory->value_string(), value());
162 if (has_writable()) {
163 CreateDataProperty(result, factory->writable_string(),
164 factory->ToBoolean(writable()));
167 CreateDataProperty(result, factory->get_string(),
get());
170 CreateDataProperty(result, factory->set_string(),
set());
172 if (has_enumerable()) {
173 CreateDataProperty(result, factory->enumerable_string(),
174 factory->ToBoolean(enumerable()));
176 if (has_configurable()) {
177 CreateDataProperty(result, factory->configurable_string(),
178 factory->ToBoolean(configurable()));
187 bool PropertyDescriptor::ToPropertyDescriptor(Isolate* isolate,
189 PropertyDescriptor* desc) {
192 if (!obj->IsJSReceiver()) {
193 isolate->Throw(*isolate->factory()->NewTypeError(
194 MessageTemplate::kPropertyDescObject, obj));
198 DCHECK(desc->is_empty());
200 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(obj);
201 if (ToPropertyDescriptorFastPath(isolate, receiver, desc)) {
206 Handle<Object> enumerable;
208 if (!GetPropertyIfPresent(receiver, isolate->factory()->enumerable_string(),
213 if (!enumerable.is_null()) {
214 desc->set_enumerable(enumerable->BooleanValue(isolate));
218 Handle<Object> configurable;
220 if (!GetPropertyIfPresent(receiver, isolate->factory()->configurable_string(),
225 if (!configurable.is_null()) {
226 desc->set_configurable(configurable->BooleanValue(isolate));
230 Handle<Object> value;
232 if (!GetPropertyIfPresent(receiver, isolate->factory()->value_string(),
237 if (!value.is_null()) desc->set_value(value);
240 Handle<Object> writable;
242 if (!GetPropertyIfPresent(receiver, isolate->factory()->writable_string(),
247 if (!writable.is_null()) desc->set_writable(writable->BooleanValue(isolate));
250 Handle<Object> getter;
252 if (!GetPropertyIfPresent(receiver, isolate->factory()->get_string(),
256 if (!getter.is_null()) {
259 if (!getter->IsCallable() && !getter->IsUndefined(isolate)) {
260 isolate->Throw(*isolate->factory()->NewTypeError(
261 MessageTemplate::kObjectGetterCallable, getter));
265 desc->set_get(getter);
268 Handle<Object> setter;
270 if (!GetPropertyIfPresent(receiver, isolate->factory()->set_string(),
274 if (!setter.is_null()) {
277 if (!setter->IsCallable() && !setter->IsUndefined(isolate)) {
278 isolate->Throw(*isolate->factory()->NewTypeError(
279 MessageTemplate::kObjectSetterCallable, setter));
283 desc->set_set(setter);
289 if ((desc->has_get() || desc->has_set()) &&
290 (desc->has_value() || desc->has_writable())) {
291 isolate->Throw(*isolate->factory()->NewTypeError(
292 MessageTemplate::kValueAndAccessor, obj));
303 void PropertyDescriptor::CompletePropertyDescriptor(Isolate* isolate,
304 PropertyDescriptor* desc) {
313 if (!IsAccessorDescriptor(desc)) {
316 if (!desc->has_value()) {
317 desc->set_value(isolate->factory()->undefined_value());
321 if (!desc->has_writable()) desc->set_writable(
false);
326 if (!desc->has_get()) {
327 desc->set_get(isolate->factory()->undefined_value());
331 if (!desc->has_set()) {
332 desc->set_set(isolate->factory()->undefined_value());
337 if (!desc->has_enumerable()) desc->set_enumerable(
false);
340 if (!desc->has_configurable()) desc->set_configurable(
false);
344 Handle<PropertyDescriptorObject> PropertyDescriptor::ToPropertyDescriptorObject(
346 Handle<PropertyDescriptorObject> obj = Handle<PropertyDescriptorObject>::cast(
347 isolate->factory()->NewFixedArray(PropertyDescriptorObject::kLength));
350 PropertyDescriptorObject::IsEnumerableBit::encode(enumerable_) |
351 PropertyDescriptorObject::HasEnumerableBit::encode(has_enumerable_) |
352 PropertyDescriptorObject::IsConfigurableBit::encode(configurable_) |
353 PropertyDescriptorObject::HasConfigurableBit::encode(has_configurable_) |
354 PropertyDescriptorObject::IsWritableBit::encode(writable_) |
355 PropertyDescriptorObject::HasWritableBit::encode(has_writable_) |
356 PropertyDescriptorObject::HasValueBit::encode(has_value()) |
357 PropertyDescriptorObject::HasGetBit::encode(has_get()) |
358 PropertyDescriptorObject::HasSetBit::encode(has_set());
360 obj->set(PropertyDescriptorObject::kFlagsIndex, Smi::FromInt(flags));
362 obj->set(PropertyDescriptorObject::kValueIndex,
363 has_value() ? *value_ : ReadOnlyRoots(isolate).the_hole_value());
364 obj->set(PropertyDescriptorObject::kGetIndex,
365 has_get() ? *get_ : ReadOnlyRoots(isolate).the_hole_value());
366 obj->set(PropertyDescriptorObject::kSetIndex,
367 has_set() ? *set_ : ReadOnlyRoots(isolate).the_hole_value());