Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/property-descriptor.cc b/src/property-descriptor.cc
new file mode 100644
index 0000000..243a9fa
--- /dev/null
+++ b/src/property-descriptor.cc
@@ -0,0 +1,300 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/property-descriptor.h"
+
+#include "src/bootstrapper.h"
+#include "src/factory.h"
+#include "src/isolate-inl.h"
+#include "src/lookup.h"
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Helper function for ToPropertyDescriptor. Comments describe steps for
+// "enumerable", other properties are handled the same way.
+// Returns false if an exception was thrown.
+bool GetPropertyIfPresent(Handle<Object> obj, Handle<String> name,
+                          Handle<Object>* value) {
+  LookupIterator it(obj, name);
+  // 4. Let hasEnumerable be HasProperty(Obj, "enumerable").
+  Maybe<bool> has_property = JSReceiver::HasProperty(&it);
+  // 5. ReturnIfAbrupt(hasEnumerable).
+  if (has_property.IsNothing()) return false;
+  // 6. If hasEnumerable is true, then
+  if (has_property.FromJust() == true) {
+    // 6a. Let enum be ToBoolean(Get(Obj, "enumerable")).
+    // 6b. ReturnIfAbrupt(enum).
+    if (!JSObject::GetProperty(&it).ToHandle(value)) return false;
+  }
+  return true;
+}
+
+
+// Helper function for ToPropertyDescriptor. Handles the case of "simple"
+// objects: nothing on the prototype chain, just own fast data properties.
+// Must not have observable side effects, because the slow path will restart
+// the entire conversion!
+bool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<Object> obj,
+                                  PropertyDescriptor* desc) {
+  if (!obj->IsJSObject()) return false;
+  Map* map = Handle<JSObject>::cast(obj)->map();
+  if (map->instance_type() != JS_OBJECT_TYPE) return false;
+  if (map->is_access_check_needed()) return false;
+  if (map->prototype() != *isolate->initial_object_prototype()) return false;
+  // During bootstrapping, the object_function_prototype_map hasn't been
+  // set up yet.
+  if (isolate->bootstrapper()->IsActive()) return false;
+  if (JSObject::cast(map->prototype())->map() !=
+      isolate->native_context()->object_function_prototype_map()) {
+    return false;
+  }
+  // TODO(jkummerow): support dictionary properties?
+  if (map->is_dictionary_map()) return false;
+  Handle<DescriptorArray> descs =
+      Handle<DescriptorArray>(map->instance_descriptors());
+  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
+    PropertyDetails details = descs->GetDetails(i);
+    Name* key = descs->GetKey(i);
+    Handle<Object> value;
+    switch (details.type()) {
+      case DATA:
+        value = JSObject::FastPropertyAt(Handle<JSObject>::cast(obj),
+                                         details.representation(),
+                                         FieldIndex::ForDescriptor(map, i));
+        break;
+      case DATA_CONSTANT:
+        value = handle(descs->GetConstant(i), isolate);
+        break;
+      case ACCESSOR:
+      case ACCESSOR_CONSTANT:
+        // Bail out to slow path.
+        return false;
+    }
+    Heap* heap = isolate->heap();
+    if (key == heap->enumerable_string()) {
+      desc->set_enumerable(value->BooleanValue());
+    } else if (key == heap->configurable_string()) {
+      desc->set_configurable(value->BooleanValue());
+    } else if (key == heap->value_string()) {
+      desc->set_value(value);
+    } else if (key == heap->writable_string()) {
+      desc->set_writable(value->BooleanValue());
+    } else if (key == heap->get_string()) {
+      // Bail out to slow path to throw an exception if necessary.
+      if (!value->IsCallable()) return false;
+      desc->set_get(value);
+    } else if (key == heap->set_string()) {
+      // Bail out to slow path to throw an exception if necessary.
+      if (!value->IsCallable()) return false;
+      desc->set_set(value);
+    }
+  }
+  if ((desc->has_get() || desc->has_set()) &&
+      (desc->has_value() || desc->has_writable())) {
+    // Bail out to slow path to throw an exception.
+    return false;
+  }
+  return true;
+}
+
+
+static void CreateDataProperty(Isolate* isolate, Handle<JSObject> object,
+                               Handle<String> name, Handle<Object> value) {
+  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
+  Maybe<bool> result = JSObject::CreateDataProperty(&it, value);
+  CHECK(result.IsJust() && result.FromJust());
+}
+
+
+// ES6 6.2.4.4 "FromPropertyDescriptor"
+Handle<Object> PropertyDescriptor::ToObject(Isolate* isolate) {
+  DCHECK(!(PropertyDescriptor::IsAccessorDescriptor(this) &&
+           PropertyDescriptor::IsDataDescriptor(this)));
+  Factory* factory = isolate->factory();
+  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
+  if (has_value()) {
+    CreateDataProperty(isolate, result, factory->value_string(), value());
+  }
+  if (has_writable()) {
+    CreateDataProperty(isolate, result, factory->writable_string(),
+                       factory->ToBoolean(writable()));
+  }
+  if (has_get()) {
+    CreateDataProperty(isolate, result, factory->get_string(), get());
+  }
+  if (has_set()) {
+    CreateDataProperty(isolate, result, factory->set_string(), set());
+  }
+  if (has_enumerable()) {
+    CreateDataProperty(isolate, result, factory->enumerable_string(),
+                       factory->ToBoolean(enumerable()));
+  }
+  if (has_configurable()) {
+    CreateDataProperty(isolate, result, factory->configurable_string(),
+                       factory->ToBoolean(configurable()));
+  }
+  return result;
+}
+
+
+// ES6 6.2.4.5
+// Returns false in case of exception.
+// static
+bool PropertyDescriptor::ToPropertyDescriptor(Isolate* isolate,
+                                              Handle<Object> obj,
+                                              PropertyDescriptor* desc) {
+  // 1. ReturnIfAbrupt(Obj).
+  // 2. If Type(Obj) is not Object, throw a TypeError exception.
+  if (!obj->IsJSReceiver()) {
+    isolate->Throw(*isolate->factory()->NewTypeError(
+        MessageTemplate::kPropertyDescObject, obj));
+    return false;
+  }
+  // 3. Let desc be a new Property Descriptor that initially has no fields.
+  DCHECK(desc->is_empty());
+
+  if (ToPropertyDescriptorFastPath(isolate, obj, desc)) {
+    return true;
+  }
+
+  // enumerable?
+  Handle<Object> enumerable;
+  // 4 through 6b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->enumerable_string(),
+                            &enumerable)) {
+    return false;
+  }
+  // 6c. Set the [[Enumerable]] field of desc to enum.
+  if (!enumerable.is_null()) {
+    desc->set_enumerable(enumerable->BooleanValue());
+  }
+
+  // configurable?
+  Handle<Object> configurable;
+  // 7 through 9b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->configurable_string(),
+                            &configurable)) {
+    return false;
+  }
+  // 9c. Set the [[Configurable]] field of desc to conf.
+  if (!configurable.is_null()) {
+    desc->set_configurable(configurable->BooleanValue());
+  }
+
+  // value?
+  Handle<Object> value;
+  // 10 through 12b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->value_string(), &value)) {
+    return false;
+  }
+  // 12c. Set the [[Value]] field of desc to value.
+  if (!value.is_null()) desc->set_value(value);
+
+  // writable?
+  Handle<Object> writable;
+  // 13 through 15b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->writable_string(),
+                            &writable)) {
+    return false;
+  }
+  // 15c. Set the [[Writable]] field of desc to writable.
+  if (!writable.is_null()) desc->set_writable(writable->BooleanValue());
+
+  // getter?
+  Handle<Object> getter;
+  // 16 through 18b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->get_string(), &getter)) {
+    return false;
+  }
+  if (!getter.is_null()) {
+    // 18c. If IsCallable(getter) is false and getter is not undefined,
+    // throw a TypeError exception.
+    if (!getter->IsCallable() && !getter->IsUndefined()) {
+      isolate->Throw(*isolate->factory()->NewTypeError(
+          MessageTemplate::kObjectGetterCallable, getter));
+      return false;
+    }
+    // 18d. Set the [[Get]] field of desc to getter.
+    desc->set_get(getter);
+  }
+  // setter?
+  Handle<Object> setter;
+  // 19 through 21b.
+  if (!GetPropertyIfPresent(obj, isolate->factory()->set_string(), &setter)) {
+    return false;
+  }
+  if (!setter.is_null()) {
+    // 21c. If IsCallable(setter) is false and setter is not undefined,
+    // throw a TypeError exception.
+    if (!setter->IsCallable() && !setter->IsUndefined()) {
+      isolate->Throw(*isolate->factory()->NewTypeError(
+          MessageTemplate::kObjectSetterCallable, setter));
+      return false;
+    }
+    // 21d. Set the [[Set]] field of desc to setter.
+    desc->set_set(setter);
+  }
+
+  // 22. If either desc.[[Get]] or desc.[[Set]] is present, then
+  // 22a. If either desc.[[Value]] or desc.[[Writable]] is present,
+  // throw a TypeError exception.
+  if ((desc->has_get() || desc->has_set()) &&
+      (desc->has_value() || desc->has_writable())) {
+    isolate->Throw(*isolate->factory()->NewTypeError(
+        MessageTemplate::kValueAndAccessor, obj));
+    return false;
+  }
+
+  // 23. Return desc.
+  return true;
+}
+
+
+// ES6 6.2.4.6
+// static
+void PropertyDescriptor::CompletePropertyDescriptor(Isolate* isolate,
+                                                    PropertyDescriptor* desc) {
+  // 1. ReturnIfAbrupt(Desc).
+  // 2. Assert: Desc is a Property Descriptor.
+  // 3. Let like be Record{
+  //        [[Value]]: undefined, [[Writable]]: false,
+  //        [[Get]]: undefined, [[Set]]: undefined,
+  //        [[Enumerable]]: false, [[Configurable]]: false}.
+  // 4. If either IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true,
+  // then:
+  if (!IsAccessorDescriptor(desc)) {
+    // 4a. If Desc does not have a [[Value]] field, set Desc.[[Value]] to
+    //     like.[[Value]].
+    if (!desc->has_value()) {
+      desc->set_value(isolate->factory()->undefined_value());
+    }
+    // 4b. If Desc does not have a [[Writable]] field, set Desc.[[Writable]]
+    //     to like.[[Writable]].
+    if (!desc->has_writable()) desc->set_writable(false);
+  } else {
+    // 5. Else,
+    // 5a. If Desc does not have a [[Get]] field, set Desc.[[Get]] to
+    //     like.[[Get]].
+    if (!desc->has_get()) {
+      desc->set_get(isolate->factory()->undefined_value());
+    }
+    // 5b. If Desc does not have a [[Set]] field, set Desc.[[Set]] to
+    //     like.[[Set]].
+    if (!desc->has_set()) {
+      desc->set_set(isolate->factory()->undefined_value());
+    }
+  }
+  // 6. If Desc does not have an [[Enumerable]] field, set
+  //    Desc.[[Enumerable]] to like.[[Enumerable]].
+  if (!desc->has_enumerable()) desc->set_enumerable(false);
+  // 7. If Desc does not have a [[Configurable]] field, set
+  //    Desc.[[Configurable]] to like.[[Configurable]].
+  if (!desc->has_configurable()) desc->set_configurable(false);
+  // 8. Return Desc.
+}
+
+}  // namespace internal
+}  // namespace v8