| Index: src/runtime/runtime-object.cc
|
| diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
|
| index d119867b3044480881e24e890a69092b64430cc5..b3b917b03ab2eafc8bebc5a9d212517b4d250ea9 100644
|
| --- a/src/runtime/runtime-object.cc
|
| +++ b/src/runtime/runtime-object.cc
|
| @@ -26,8 +26,7 @@
|
|
|
| MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
|
| Handle<Object> object,
|
| - uint32_t index,
|
| - LanguageMode language_mode) {
|
| + uint32_t index) {
|
| // Handle [] indexing on Strings
|
| if (object->IsString() &&
|
| index < static_cast<uint32_t>(String::cast(*object)->length())) {
|
| @@ -35,7 +34,7 @@
|
| if (!result->IsUndefined()) return result;
|
| }
|
|
|
| - return Object::GetElement(isolate, object, index, language_mode);
|
| + return Object::GetElement(isolate, object, index);
|
| }
|
|
|
|
|
| @@ -53,8 +52,7 @@
|
|
|
| MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
|
| Handle<Object> object,
|
| - Handle<Object> key,
|
| - LanguageMode language_mode) {
|
| + Handle<Object> key) {
|
| if (object->IsUndefined() || object->IsNull()) {
|
| THROW_NEW_ERROR(
|
| isolate,
|
| @@ -65,7 +63,7 @@
|
| // Check if the given key is an array index.
|
| uint32_t index = 0;
|
| if (key->ToArrayIndex(&index)) {
|
| - return GetElementOrCharAt(isolate, object, index, language_mode);
|
| + return GetElementOrCharAt(isolate, object, index);
|
| }
|
|
|
| // Convert the key to a name - possibly by calling back into JavaScript.
|
| @@ -79,8 +77,320 @@
|
| if (name->AsArrayIndex(&index)) {
|
| return GetElementOrCharAt(isolate, object, index);
|
| } else {
|
| - return Object::GetProperty(object, name, language_mode);
|
| - }
|
| + return Object::GetProperty(object, name);
|
| + }
|
| +}
|
| +
|
| +
|
| +MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
|
| + Handle<Object> object,
|
| + Handle<Object> key,
|
| + Handle<Object> value,
|
| + LanguageMode language_mode) {
|
| + if (object->IsUndefined() || object->IsNull()) {
|
| + THROW_NEW_ERROR(
|
| + isolate,
|
| + NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
|
| + Object);
|
| + }
|
| +
|
| + // Check if the given key is an array index.
|
| + uint32_t index = 0;
|
| + if (key->ToArrayIndex(&index)) {
|
| + // TODO(verwaest): Support other objects as well.
|
| + if (!object->IsJSReceiver()) return value;
|
| + return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
|
| + value, language_mode);
|
| + }
|
| +
|
| + Handle<Name> name;
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
|
| +
|
| + LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
|
| + // TODO(verwaest): Support other objects as well.
|
| + if (it.IsElement() && !object->IsJSReceiver()) return value;
|
| + return Object::SetProperty(&it, value, language_mode,
|
| + Object::MAY_BE_STORE_FROM_KEYED);
|
| +}
|
| +
|
| +
|
| +MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
|
| + Handle<Object> obj) {
|
| + // We don't expect access checks to be needed on JSProxy objects.
|
| + DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
|
| + PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
| + do {
|
| + if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
|
| + !isolate->MayAccess(
|
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
|
| + isolate->ReportFailedAccessCheck(
|
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
|
| + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return isolate->factory()->undefined_value();
|
| + }
|
| + iter.AdvanceIgnoringProxies();
|
| + if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
|
| + return PrototypeIterator::GetCurrent(iter);
|
| + }
|
| + } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
|
| + return PrototypeIterator::GetCurrent(iter);
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_GetPrototype) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + Runtime::GetPrototype(isolate, obj));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
| + DCHECK(!obj->IsAccessCheckNeeded());
|
| + DCHECK(!obj->map()->is_observed());
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, JSObject::SetPrototype(obj, prototype, false));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_SetPrototype) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
| + if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
|
| + isolate->ReportFailedAccessCheck(obj);
|
| + RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| + return isolate->heap()->undefined_value();
|
| + }
|
| + if (obj->map()->is_observed()) {
|
| + Handle<Object> old_value =
|
| + Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, JSObject::SetPrototype(obj, prototype, true));
|
| +
|
| + Handle<Object> new_value =
|
| + Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
|
| + if (!new_value->SameValue(*old_value)) {
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, JSObject::EnqueueChangeRecord(
|
| + obj, "setPrototype", isolate->factory()->proto_string(),
|
| + old_value));
|
| + }
|
| + return *result;
|
| + }
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, JSObject::SetPrototype(obj, prototype, true));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
|
| + HandleScope shs(isolate);
|
| + DCHECK(args.length() == 2);
|
| + // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
|
| + PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
|
| + while (true) {
|
| + iter.AdvanceIgnoringProxies();
|
| + if (iter.IsAtEnd()) return isolate->heap()->false_value();
|
| + if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
|
| + }
|
| +}
|
| +
|
| +
|
| +// Enumerator used as indices into the array returned from GetOwnProperty
|
| +enum PropertyDescriptorIndices {
|
| + IS_ACCESSOR_INDEX,
|
| + VALUE_INDEX,
|
| + GETTER_INDEX,
|
| + SETTER_INDEX,
|
| + WRITABLE_INDEX,
|
| + ENUMERABLE_INDEX,
|
| + CONFIGURABLE_INDEX,
|
| + DESCRIPTOR_SIZE
|
| +};
|
| +
|
| +
|
| +MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
|
| + Handle<JSObject> obj,
|
| + Handle<Name> name) {
|
| + Heap* heap = isolate->heap();
|
| + Factory* factory = isolate->factory();
|
| +
|
| + PropertyAttributes attrs;
|
| + // Get attributes.
|
| + LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
|
| + LookupIterator::HIDDEN);
|
| + Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
|
| +
|
| + if (!maybe.IsJust()) return MaybeHandle<Object>();
|
| + attrs = maybe.FromJust();
|
| + if (attrs == ABSENT) return factory->undefined_value();
|
| +
|
| + DCHECK(!isolate->has_pending_exception());
|
| + Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
|
| + elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
|
| + elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
|
| +
|
| + bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
|
| + it.GetAccessors()->IsAccessorPair();
|
| + elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
|
| +
|
| + if (is_accessor_pair) {
|
| + Handle<AccessorPair> accessors =
|
| + Handle<AccessorPair>::cast(it.GetAccessors());
|
| + Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
|
| + Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
|
| + elms->set(GETTER_INDEX, *getter);
|
| + elms->set(SETTER_INDEX, *setter);
|
| + } else {
|
| + Handle<Object> value;
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
|
| + Object);
|
| + elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
|
| + elms->set(VALUE_INDEX, *value);
|
| + }
|
| +
|
| + return factory->NewJSArrayWithElements(elms);
|
| +}
|
| +
|
| +
|
| +// Returns an array with the property description:
|
| +// if args[1] is not a property on args[0]
|
| +// returns undefined
|
| +// if args[1] is a data property on args[0]
|
| +// [false, value, Writeable, Enumerable, Configurable]
|
| +// if args[1] is an accessor on args[0]
|
| +// [true, GetFunction, SetFunction, Enumerable, Configurable]
|
| +RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + GetOwnProperty(isolate, obj, name));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_PreventExtensions) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + JSObject::PreventExtensions(obj));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_IsExtensible) {
|
| + SealHandleScope shs(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| + return isolate->heap()->ToBoolean(obj->IsExtensible());
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
|
| + Handle<Map> old_map(object->map());
|
| + bool needs_access_checks = old_map->is_access_check_needed();
|
| + if (needs_access_checks) {
|
| + // Copy map so it won't interfere constructor's initial map.
|
| + Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
|
| + new_map->set_is_access_check_needed(false);
|
| + JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
|
| + }
|
| + return isolate->heap()->ToBoolean(needs_access_checks);
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| + Handle<Map> old_map(object->map());
|
| + RUNTIME_ASSERT(!old_map->is_access_check_needed());
|
| + // Copy map so it won't interfere constructor's initial map.
|
| + Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
|
| + new_map->set_is_access_check_needed(true);
|
| + JSObject::MigrateToMap(object, new_map);
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| + CONVERT_SMI_ARG_CHECKED(properties, 1);
|
| + // Conservative upper limit to prevent fuzz tests from going OOM.
|
| + RUNTIME_ASSERT(properties <= 100000);
|
| + if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
|
| + JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
|
| + "OptimizeForAdding");
|
| + }
|
| + return *object;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| +
|
| + // %ObjectFreeze is a fast path and these cases are handled elsewhere.
|
| + RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
|
| + !object->map()->is_observed() && !object->IsJSProxy());
|
| +
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_ObjectSeal) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| +
|
| + // %ObjectSeal is a fast path and these cases are handled elsewhere.
|
| + RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
|
| + !object->map()->is_observed() && !object->IsJSProxy());
|
| +
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| +RUNTIME_FUNCTION(Runtime_GetProperty) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| +
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
|
| + Handle<Object> result;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, Runtime::GetObjectProperty(isolate, object, key));
|
| + return *result;
|
| }
|
|
|
|
|
| @@ -102,9 +412,14 @@
|
| }
|
|
|
|
|
| -MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
|
| - Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
|
| - LanguageMode language_mode) {
|
| +// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
|
| +RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 2);
|
| +
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
|
| +
|
| // Fast cases for getting named properties of the receiver JSObject
|
| // itself.
|
| //
|
| @@ -131,7 +446,7 @@
|
| PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
|
| if (cell->property_details().type() == DATA) {
|
| Object* value = cell->value();
|
| - if (!value->IsTheHole()) return Handle<Object>(value, isolate);
|
| + if (!value->IsTheHole()) return value;
|
| // If value is the hole (meaning, absent) do the general lookup.
|
| }
|
| }
|
| @@ -142,7 +457,7 @@
|
| if ((entry != NameDictionary::kNotFound) &&
|
| (dictionary->DetailsAt(entry).type() == DATA)) {
|
| Object* value = dictionary->ValueAt(entry);
|
| - return Handle<Object>(value, isolate);
|
| + return value;
|
| }
|
| }
|
| } else if (key_obj->IsSmi()) {
|
| @@ -162,9 +477,8 @@
|
| } else {
|
| elements_kind = FAST_ELEMENTS;
|
| }
|
| - RETURN_ON_EXCEPTION(
|
| - isolate, TransitionElements(js_object, elements_kind, isolate),
|
| - Object);
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, TransitionElements(js_object, elements_kind, isolate));
|
| }
|
| } else {
|
| DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
|
| @@ -174,344 +488,17 @@
|
| } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
|
| // Fast case for string indexing using [] with a smi index.
|
| Handle<String> str = Handle<String>::cast(receiver_obj);
|
| - int index = Handle<Smi>::cast(key_obj)->value();
|
| + int index = args.smi_at(1);
|
| if (index >= 0 && index < str->length()) {
|
| - return GetCharAt(str, index);
|
| + return *GetCharAt(str, index);
|
| }
|
| }
|
|
|
| // Fall back to GetObjectProperty.
|
| - return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
|
| -}
|
| -
|
| -
|
| -MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
|
| - Handle<Object> object,
|
| - Handle<Object> key,
|
| - Handle<Object> value,
|
| - LanguageMode language_mode) {
|
| - if (object->IsUndefined() || object->IsNull()) {
|
| - THROW_NEW_ERROR(
|
| - isolate,
|
| - NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
|
| - Object);
|
| - }
|
| -
|
| - // Check if the given key is an array index.
|
| - uint32_t index = 0;
|
| - if (key->ToArrayIndex(&index)) {
|
| - // TODO(verwaest): Support other objects as well.
|
| - if (!object->IsJSReceiver()) return value;
|
| - return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
|
| - value, language_mode);
|
| - }
|
| -
|
| - Handle<Name> name;
|
| - ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
|
| -
|
| - LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
|
| - // TODO(verwaest): Support other objects as well.
|
| - if (it.IsElement() && !object->IsJSReceiver()) return value;
|
| - return Object::SetProperty(&it, value, language_mode,
|
| - Object::MAY_BE_STORE_FROM_KEYED);
|
| -}
|
| -
|
| -
|
| -MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
|
| - Handle<Object> obj) {
|
| - // We don't expect access checks to be needed on JSProxy objects.
|
| - DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
|
| - PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
| - do {
|
| - if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
|
| - !isolate->MayAccess(
|
| - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
|
| - isolate->ReportFailedAccessCheck(
|
| - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
|
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - return isolate->factory()->undefined_value();
|
| - }
|
| - iter.AdvanceIgnoringProxies();
|
| - if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
|
| - return PrototypeIterator::GetCurrent(iter);
|
| - }
|
| - } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
|
| - return PrototypeIterator::GetCurrent(iter);
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_GetPrototype) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| - Runtime::GetPrototype(isolate, obj));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 2);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
| - DCHECK(!obj->IsAccessCheckNeeded());
|
| - DCHECK(!obj->map()->is_observed());
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, JSObject::SetPrototype(obj, prototype, false));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_SetPrototype) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 2);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
| - if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
|
| - isolate->ReportFailedAccessCheck(obj);
|
| - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return isolate->heap()->undefined_value();
|
| - }
|
| - if (obj->map()->is_observed()) {
|
| - Handle<Object> old_value =
|
| - Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, JSObject::SetPrototype(obj, prototype, true));
|
| -
|
| - Handle<Object> new_value =
|
| - Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
|
| - if (!new_value->SameValue(*old_value)) {
|
| - RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, JSObject::EnqueueChangeRecord(
|
| - obj, "setPrototype", isolate->factory()->proto_string(),
|
| - old_value));
|
| - }
|
| - return *result;
|
| - }
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, JSObject::SetPrototype(obj, prototype, true));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
|
| - HandleScope shs(isolate);
|
| - DCHECK(args.length() == 2);
|
| - // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
|
| - PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
|
| - while (true) {
|
| - iter.AdvanceIgnoringProxies();
|
| - if (iter.IsAtEnd()) return isolate->heap()->false_value();
|
| - if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
|
| - }
|
| -}
|
| -
|
| -
|
| -// Enumerator used as indices into the array returned from GetOwnProperty
|
| -enum PropertyDescriptorIndices {
|
| - IS_ACCESSOR_INDEX,
|
| - VALUE_INDEX,
|
| - GETTER_INDEX,
|
| - SETTER_INDEX,
|
| - WRITABLE_INDEX,
|
| - ENUMERABLE_INDEX,
|
| - CONFIGURABLE_INDEX,
|
| - DESCRIPTOR_SIZE
|
| -};
|
| -
|
| -
|
| -MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
|
| - Handle<JSObject> obj,
|
| - Handle<Name> name) {
|
| - Heap* heap = isolate->heap();
|
| - Factory* factory = isolate->factory();
|
| -
|
| - PropertyAttributes attrs;
|
| - // Get attributes.
|
| - LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
|
| - LookupIterator::HIDDEN);
|
| - Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
|
| -
|
| - if (!maybe.IsJust()) return MaybeHandle<Object>();
|
| - attrs = maybe.FromJust();
|
| - if (attrs == ABSENT) return factory->undefined_value();
|
| -
|
| - DCHECK(!isolate->has_pending_exception());
|
| - Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
|
| - elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
|
| - elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
|
| -
|
| - bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
|
| - it.GetAccessors()->IsAccessorPair();
|
| - elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
|
| -
|
| - if (is_accessor_pair) {
|
| - Handle<AccessorPair> accessors =
|
| - Handle<AccessorPair>::cast(it.GetAccessors());
|
| - Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
|
| - Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
|
| - elms->set(GETTER_INDEX, *getter);
|
| - elms->set(SETTER_INDEX, *setter);
|
| - } else {
|
| - Handle<Object> value;
|
| - ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
|
| - Object);
|
| - elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
|
| - elms->set(VALUE_INDEX, *value);
|
| - }
|
| -
|
| - return factory->NewJSArrayWithElements(elms);
|
| -}
|
| -
|
| -
|
| -// Returns an array with the property description:
|
| -// if args[1] is not a property on args[0]
|
| -// returns undefined
|
| -// if args[1] is a data property on args[0]
|
| -// [false, value, Writeable, Enumerable, Configurable]
|
| -// if args[1] is an accessor on args[0]
|
| -// [true, GetFunction, SetFunction, Enumerable, Configurable]
|
| -RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 2);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| - GetOwnProperty(isolate, obj, name));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_PreventExtensions) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| - JSObject::PreventExtensions(obj));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_IsExtensible) {
|
| - SealHandleScope shs(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| - return isolate->heap()->ToBoolean(obj->IsExtensible());
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
|
| - Handle<Map> old_map(object->map());
|
| - bool needs_access_checks = old_map->is_access_check_needed();
|
| - if (needs_access_checks) {
|
| - // Copy map so it won't interfere constructor's initial map.
|
| - Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
|
| - new_map->set_is_access_check_needed(false);
|
| - JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
|
| - }
|
| - return isolate->heap()->ToBoolean(needs_access_checks);
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| - Handle<Map> old_map(object->map());
|
| - RUNTIME_ASSERT(!old_map->is_access_check_needed());
|
| - // Copy map so it won't interfere constructor's initial map.
|
| - Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
|
| - new_map->set_is_access_check_needed(true);
|
| - JSObject::MigrateToMap(object, new_map);
|
| - return isolate->heap()->undefined_value();
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 2);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| - CONVERT_SMI_ARG_CHECKED(properties, 1);
|
| - // Conservative upper limit to prevent fuzz tests from going OOM.
|
| - RUNTIME_ASSERT(properties <= 100000);
|
| - if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
|
| - JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
|
| - "OptimizeForAdding");
|
| - }
|
| - return *object;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| -
|
| - // %ObjectFreeze is a fast path and these cases are handled elsewhere.
|
| - RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
|
| - !object->map()->is_observed() && !object->IsJSProxy());
|
| -
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_ObjectSeal) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| -
|
| - // %ObjectSeal is a fast path and these cases are handled elsewhere.
|
| - RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
|
| - !object->map()->is_observed() && !object->IsJSProxy());
|
| -
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_GetProperty) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3);
|
| -
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
|
| - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
|
| -
|
| Handle<Object> result;
|
| ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| isolate, result,
|
| - Runtime::GetObjectProperty(isolate, object, key, language_mode));
|
| - return *result;
|
| -}
|
| -
|
| -
|
| -RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
|
| - HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3);
|
| -
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
|
| - CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
|
| - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
|
| -
|
| - Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver_obj,
|
| - key_obj, language_mode));
|
| + Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
|
| return *result;
|
| }
|
|
|
|
|