1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/property-descriptor.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/bootstrapper.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/lookup.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-inl.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Helper function for ToPropertyDescriptor. Comments describe steps for
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// "enumerable", other properties are handled the same way.
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Returns false if an exception was thrown.
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool GetPropertyIfPresent(Handle<Object> obj, Handle<String> name,
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          Handle<Object>* value) {
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LookupIterator it(obj, name);
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 4. Let hasEnumerable be HasProperty(Obj, "enumerable").
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Maybe<bool> has_property = JSReceiver::HasProperty(&it);
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 5. ReturnIfAbrupt(hasEnumerable).
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_property.IsNothing()) return false;
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 6. If hasEnumerable is true, then
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_property.FromJust() == true) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 6a. Let enum be ToBoolean(Get(Obj, "enumerable")).
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 6b. ReturnIfAbrupt(enum).
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!JSObject::GetProperty(&it).ToHandle(value)) return false;
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Helper function for ToPropertyDescriptor. Handles the case of "simple"
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// objects: nothing on the prototype chain, just own fast data properties.
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Must not have observable side effects, because the slow path will restart
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the entire conversion!
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<Object> obj,
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  PropertyDescriptor* desc) {
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!obj->IsJSObject()) return false;
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Map* map = Handle<JSObject>::cast(obj)->map();
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (map->instance_type() != JS_OBJECT_TYPE) return false;
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (map->is_access_check_needed()) return false;
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (map->prototype() != *isolate->initial_object_prototype()) return false;
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // During bootstrapping, the object_function_prototype_map hasn't been
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // set up yet.
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (isolate->bootstrapper()->IsActive()) return false;
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (JSObject::cast(map->prototype())->map() !=
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      isolate->native_context()->object_function_prototype_map()) {
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(jkummerow): support dictionary properties?
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (map->is_dictionary_map()) return false;
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<DescriptorArray> descs =
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<DescriptorArray>(map->instance_descriptors());
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PropertyDetails details = descs->GetDetails(i);
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Name* key = descs->GetKey(i);
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<Object> value;
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (details.type()) {
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case DATA:
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        value = JSObject::FastPropertyAt(Handle<JSObject>::cast(obj),
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         details.representation(),
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         FieldIndex::ForDescriptor(map, i));
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case DATA_CONSTANT:
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        value = handle(descs->GetConstant(i), isolate);
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ACCESSOR:
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case ACCESSOR_CONSTANT:
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Bail out to slow path.
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return false;
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Heap* heap = isolate->heap();
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (key == heap->enumerable_string()) {
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_enumerable(value->BooleanValue());
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (key == heap->configurable_string()) {
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_configurable(value->BooleanValue());
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (key == heap->value_string()) {
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_value(value);
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (key == heap->writable_string()) {
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_writable(value->BooleanValue());
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (key == heap->get_string()) {
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Bail out to slow path to throw an exception if necessary.
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!value->IsCallable()) return false;
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_get(value);
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (key == heap->set_string()) {
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Bail out to slow path to throw an exception if necessary.
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!value->IsCallable()) return false;
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_set(value);
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if ((desc->has_get() || desc->has_set()) &&
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (desc->has_value() || desc->has_writable())) {
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Bail out to slow path to throw an exception.
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CreateDataProperty(Isolate* isolate, Handle<JSObject> object,
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Handle<String> name, Handle<Object> value) {
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Maybe<bool> result = JSObject::CreateDataProperty(&it, value);
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(result.IsJust() && result.FromJust());
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 6.2.4.4 "FromPropertyDescriptor"
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHandle<Object> PropertyDescriptor::ToObject(Isolate* isolate) {
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!(PropertyDescriptor::IsAccessorDescriptor(this) &&
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           PropertyDescriptor::IsDataDescriptor(this)));
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Factory* factory = isolate->factory();
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_value()) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->value_string(), value());
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_writable()) {
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->writable_string(),
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       factory->ToBoolean(writable()));
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_get()) {
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->get_string(), get());
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_set()) {
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->set_string(), set());
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_enumerable()) {
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->enumerable_string(),
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       factory->ToBoolean(enumerable()));
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (has_configurable()) {
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CreateDataProperty(isolate, result, factory->configurable_string(),
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       factory->ToBoolean(configurable()));
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return result;
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 6.2.4.5
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Returns false in case of exception.
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool PropertyDescriptor::ToPropertyDescriptor(Isolate* isolate,
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              Handle<Object> obj,
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                              PropertyDescriptor* desc) {
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 1. ReturnIfAbrupt(Obj).
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 2. If Type(Obj) is not Object, throw a TypeError exception.
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!obj->IsJSReceiver()) {
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    isolate->Throw(*isolate->factory()->NewTypeError(
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        MessageTemplate::kPropertyDescObject, obj));
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 3. Let desc be a new Property Descriptor that initially has no fields.
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(desc->is_empty());
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (ToPropertyDescriptorFastPath(isolate, obj, desc)) {
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return true;
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // enumerable?
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> enumerable;
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 4 through 6b.
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->enumerable_string(),
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            &enumerable)) {
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 6c. Set the [[Enumerable]] field of desc to enum.
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!enumerable.is_null()) {
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    desc->set_enumerable(enumerable->BooleanValue());
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // configurable?
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> configurable;
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 7 through 9b.
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->configurable_string(),
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            &configurable)) {
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 9c. Set the [[Configurable]] field of desc to conf.
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!configurable.is_null()) {
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    desc->set_configurable(configurable->BooleanValue());
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // value?
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> value;
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 10 through 12b.
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->value_string(), &value)) {
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 12c. Set the [[Value]] field of desc to value.
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!value.is_null()) desc->set_value(value);
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // writable?
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> writable;
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 13 through 15b.
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->writable_string(),
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            &writable)) {
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 15c. Set the [[Writable]] field of desc to writable.
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!writable.is_null()) desc->set_writable(writable->BooleanValue());
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // getter?
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> getter;
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 16 through 18b.
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->get_string(), &getter)) {
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!getter.is_null()) {
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 18c. If IsCallable(getter) is false and getter is not undefined,
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // throw a TypeError exception.
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!getter->IsCallable() && !getter->IsUndefined()) {
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      isolate->Throw(*isolate->factory()->NewTypeError(
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          MessageTemplate::kObjectGetterCallable, getter));
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return false;
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 18d. Set the [[Get]] field of desc to getter.
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    desc->set_get(getter);
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // setter?
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Object> setter;
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 19 through 21b.
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!GetPropertyIfPresent(obj, isolate->factory()->set_string(), &setter)) {
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!setter.is_null()) {
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 21c. If IsCallable(setter) is false and setter is not undefined,
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // throw a TypeError exception.
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!setter->IsCallable() && !setter->IsUndefined()) {
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      isolate->Throw(*isolate->factory()->NewTypeError(
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          MessageTemplate::kObjectSetterCallable, setter));
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return false;
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 21d. Set the [[Set]] field of desc to setter.
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    desc->set_set(setter);
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 22. If either desc.[[Get]] or desc.[[Set]] is present, then
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 22a. If either desc.[[Value]] or desc.[[Writable]] is present,
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // throw a TypeError exception.
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if ((desc->has_get() || desc->has_set()) &&
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (desc->has_value() || desc->has_writable())) {
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    isolate->Throw(*isolate->factory()->NewTypeError(
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        MessageTemplate::kValueAndAccessor, obj));
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return false;
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 23. Return desc.
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return true;
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 6.2.4.6
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyDescriptor::CompletePropertyDescriptor(Isolate* isolate,
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                    PropertyDescriptor* desc) {
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 1. ReturnIfAbrupt(Desc).
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 2. Assert: Desc is a Property Descriptor.
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 3. Let like be Record{
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //        [[Value]]: undefined, [[Writable]]: false,
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //        [[Get]]: undefined, [[Set]]: undefined,
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //        [[Enumerable]]: false, [[Configurable]]: false}.
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 4. If either IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true,
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // then:
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!IsAccessorDescriptor(desc)) {
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 4a. If Desc does not have a [[Value]] field, set Desc.[[Value]] to
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //     like.[[Value]].
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!desc->has_value()) {
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_value(isolate->factory()->undefined_value());
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 4b. If Desc does not have a [[Writable]] field, set Desc.[[Writable]]
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //     to like.[[Writable]].
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!desc->has_writable()) desc->set_writable(false);
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 5. Else,
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 5a. If Desc does not have a [[Get]] field, set Desc.[[Get]] to
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //     like.[[Get]].
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!desc->has_get()) {
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_get(isolate->factory()->undefined_value());
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // 5b. If Desc does not have a [[Set]] field, set Desc.[[Set]] to
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //     like.[[Set]].
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!desc->has_set()) {
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      desc->set_set(isolate->factory()->undefined_value());
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 6. If Desc does not have an [[Enumerable]] field, set
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    Desc.[[Enumerable]] to like.[[Enumerable]].
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!desc->has_enumerable()) desc->set_enumerable(false);
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 7. If Desc does not have a [[Configurable]] field, set
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //    Desc.[[Configurable]] to like.[[Configurable]].
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!desc->has_configurable()) desc->set_configurable(false);
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // 8. Return Desc.
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
301