| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/debug.h" | 9 #include "src/debug.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| 11 #include "src/runtime/runtime.h" | 11 #include "src/runtime/runtime.h" |
| 12 #include "src/runtime/runtime-utils.h" | 12 #include "src/runtime/runtime-utils.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 // Returns a single character string where first character equals | 17 // Returns a single character string where first character equals |
| 18 // string->Get(index). | 18 // string->Get(index). |
| 19 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { | 19 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { |
| 20 DCHECK_LT(index, static_cast<uint32_t>(string->length())); | 20 DCHECK_LT(index, static_cast<uint32_t>(string->length())); |
| 21 Factory* factory = string->GetIsolate()->factory(); | 21 Factory* factory = string->GetIsolate()->factory(); |
| 22 return factory->LookupSingleCharacterStringFromCode( | 22 return factory->LookupSingleCharacterStringFromCode( |
| 23 String::Flatten(string)->Get(index)); | 23 String::Flatten(string)->Get(index)); |
| 24 } | 24 } |
| 25 | 25 |
| 26 | 26 |
| 27 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate, | 27 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate, |
| 28 Handle<Object> object, | 28 Handle<Object> object, |
| 29 uint32_t index) { | 29 uint32_t index, |
| 30 LanguageMode language_mode) { |
| 30 // Handle [] indexing on Strings | 31 // Handle [] indexing on Strings |
| 31 if (object->IsString() && | 32 if (object->IsString() && |
| 32 index < static_cast<uint32_t>(String::cast(*object)->length())) { | 33 index < static_cast<uint32_t>(String::cast(*object)->length())) { |
| 33 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); | 34 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); |
| 34 if (!result->IsUndefined()) return result; | 35 if (!result->IsUndefined()) return result; |
| 35 } | 36 } |
| 36 | 37 |
| 37 return Object::GetElement(isolate, object, index); | 38 return Object::GetElement(isolate, object, index, language_mode); |
| 38 } | 39 } |
| 39 | 40 |
| 40 | 41 |
| 41 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) { | 42 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) { |
| 42 if (key->IsName()) { | 43 if (key->IsName()) { |
| 43 return Handle<Name>::cast(key); | 44 return Handle<Name>::cast(key); |
| 44 } else { | 45 } else { |
| 45 Handle<Object> converted; | 46 Handle<Object> converted; |
| 46 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | 47 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
| 47 Execution::ToString(isolate, key), Name); | 48 Execution::ToString(isolate, key), Name); |
| 48 return Handle<Name>::cast(converted); | 49 return Handle<Name>::cast(converted); |
| 49 } | 50 } |
| 50 } | 51 } |
| 51 | 52 |
| 52 | 53 |
| 53 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, | 54 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, |
| 54 Handle<Object> object, | 55 Handle<Object> object, |
| 55 Handle<Object> key) { | 56 Handle<Object> key, |
| 57 LanguageMode language_mode) { |
| 56 if (object->IsUndefined() || object->IsNull()) { | 58 if (object->IsUndefined() || object->IsNull()) { |
| 57 THROW_NEW_ERROR( | 59 THROW_NEW_ERROR( |
| 58 isolate, | 60 isolate, |
| 59 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object), | 61 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object), |
| 60 Object); | 62 Object); |
| 61 } | 63 } |
| 62 | 64 |
| 63 // Check if the given key is an array index. | 65 // Check if the given key is an array index. |
| 64 uint32_t index = 0; | 66 uint32_t index = 0; |
| 65 if (key->ToArrayIndex(&index)) { | 67 if (key->ToArrayIndex(&index)) { |
| 66 return GetElementOrCharAt(isolate, object, index); | 68 return GetElementOrCharAt(isolate, object, index, language_mode); |
| 67 } | 69 } |
| 68 | 70 |
| 69 // Convert the key to a name - possibly by calling back into JavaScript. | 71 // Convert the key to a name - possibly by calling back into JavaScript. |
| 70 Handle<Name> name; | 72 Handle<Name> name; |
| 71 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); | 73 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); |
| 72 | 74 |
| 73 // Check if the name is trivially convertible to an index and get | 75 // Check if the name is trivially convertible to an index and get |
| 74 // the element if so. | 76 // the element if so. |
| 75 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and | 77 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and |
| 76 // remove the special casing here. | 78 // remove the special casing here. |
| 77 if (name->AsArrayIndex(&index)) { | 79 if (name->AsArrayIndex(&index)) { |
| 78 return GetElementOrCharAt(isolate, object, index); | 80 return GetElementOrCharAt(isolate, object, index); |
| 79 } else { | 81 } else { |
| 80 return Object::GetProperty(object, name); | 82 return Object::GetProperty(object, name, language_mode); |
| 81 } | 83 } |
| 82 } | 84 } |
| 83 | 85 |
| 84 | 86 |
| 85 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, | |
| 86 Handle<Object> object, | |
| 87 Handle<Object> key, | |
| 88 Handle<Object> value, | |
| 89 LanguageMode language_mode) { | |
| 90 if (object->IsUndefined() || object->IsNull()) { | |
| 91 THROW_NEW_ERROR( | |
| 92 isolate, | |
| 93 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), | |
| 94 Object); | |
| 95 } | |
| 96 | |
| 97 // Check if the given key is an array index. | |
| 98 uint32_t index = 0; | |
| 99 if (key->ToArrayIndex(&index)) { | |
| 100 // TODO(verwaest): Support other objects as well. | |
| 101 if (!object->IsJSReceiver()) return value; | |
| 102 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, | |
| 103 value, language_mode); | |
| 104 } | |
| 105 | |
| 106 Handle<Name> name; | |
| 107 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); | |
| 108 | |
| 109 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); | |
| 110 // TODO(verwaest): Support other objects as well. | |
| 111 if (it.IsElement() && !object->IsJSReceiver()) return value; | |
| 112 return Object::SetProperty(&it, value, language_mode, | |
| 113 Object::MAY_BE_STORE_FROM_KEYED); | |
| 114 } | |
| 115 | |
| 116 | |
| 117 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, | |
| 118 Handle<Object> obj) { | |
| 119 // We don't expect access checks to be needed on JSProxy objects. | |
| 120 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | |
| 121 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | |
| 122 do { | |
| 123 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && | |
| 124 !isolate->MayAccess( | |
| 125 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) { | |
| 126 isolate->ReportFailedAccessCheck( | |
| 127 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | |
| 128 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
| 129 return isolate->factory()->undefined_value(); | |
| 130 } | |
| 131 iter.AdvanceIgnoringProxies(); | |
| 132 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
| 133 return PrototypeIterator::GetCurrent(iter); | |
| 134 } | |
| 135 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); | |
| 136 return PrototypeIterator::GetCurrent(iter); | |
| 137 } | |
| 138 | |
| 139 | |
| 140 RUNTIME_FUNCTION(Runtime_GetPrototype) { | |
| 141 HandleScope scope(isolate); | |
| 142 DCHECK(args.length() == 1); | |
| 143 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); | |
| 144 Handle<Object> result; | |
| 145 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 146 Runtime::GetPrototype(isolate, obj)); | |
| 147 return *result; | |
| 148 } | |
| 149 | |
| 150 | |
| 151 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { | |
| 152 HandleScope scope(isolate); | |
| 153 DCHECK(args.length() == 2); | |
| 154 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 155 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); | |
| 156 DCHECK(!obj->IsAccessCheckNeeded()); | |
| 157 DCHECK(!obj->map()->is_observed()); | |
| 158 Handle<Object> result; | |
| 159 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 160 isolate, result, JSObject::SetPrototype(obj, prototype, false)); | |
| 161 return *result; | |
| 162 } | |
| 163 | |
| 164 | |
| 165 RUNTIME_FUNCTION(Runtime_SetPrototype) { | |
| 166 HandleScope scope(isolate); | |
| 167 DCHECK(args.length() == 2); | |
| 168 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 169 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); | |
| 170 if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) { | |
| 171 isolate->ReportFailedAccessCheck(obj); | |
| 172 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
| 173 return isolate->heap()->undefined_value(); | |
| 174 } | |
| 175 if (obj->map()->is_observed()) { | |
| 176 Handle<Object> old_value = | |
| 177 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); | |
| 178 Handle<Object> result; | |
| 179 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 180 isolate, result, JSObject::SetPrototype(obj, prototype, true)); | |
| 181 | |
| 182 Handle<Object> new_value = | |
| 183 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); | |
| 184 if (!new_value->SameValue(*old_value)) { | |
| 185 RETURN_FAILURE_ON_EXCEPTION( | |
| 186 isolate, JSObject::EnqueueChangeRecord( | |
| 187 obj, "setPrototype", isolate->factory()->proto_string(), | |
| 188 old_value)); | |
| 189 } | |
| 190 return *result; | |
| 191 } | |
| 192 Handle<Object> result; | |
| 193 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 194 isolate, result, JSObject::SetPrototype(obj, prototype, true)); | |
| 195 return *result; | |
| 196 } | |
| 197 | |
| 198 | |
| 199 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) { | |
| 200 HandleScope shs(isolate); | |
| 201 DCHECK(args.length() == 2); | |
| 202 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). | |
| 203 CONVERT_ARG_HANDLE_CHECKED(Object, O, 0); | |
| 204 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); | |
| 205 PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER); | |
| 206 while (true) { | |
| 207 iter.AdvanceIgnoringProxies(); | |
| 208 if (iter.IsAtEnd()) return isolate->heap()->false_value(); | |
| 209 if (iter.IsAtEnd(O)) return isolate->heap()->true_value(); | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 | |
| 214 // Enumerator used as indices into the array returned from GetOwnProperty | |
| 215 enum PropertyDescriptorIndices { | |
| 216 IS_ACCESSOR_INDEX, | |
| 217 VALUE_INDEX, | |
| 218 GETTER_INDEX, | |
| 219 SETTER_INDEX, | |
| 220 WRITABLE_INDEX, | |
| 221 ENUMERABLE_INDEX, | |
| 222 CONFIGURABLE_INDEX, | |
| 223 DESCRIPTOR_SIZE | |
| 224 }; | |
| 225 | |
| 226 | |
| 227 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, | |
| 228 Handle<JSObject> obj, | |
| 229 Handle<Name> name) { | |
| 230 Heap* heap = isolate->heap(); | |
| 231 Factory* factory = isolate->factory(); | |
| 232 | |
| 233 PropertyAttributes attrs; | |
| 234 // Get attributes. | |
| 235 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name, | |
| 236 LookupIterator::HIDDEN); | |
| 237 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it); | |
| 238 | |
| 239 if (!maybe.IsJust()) return MaybeHandle<Object>(); | |
| 240 attrs = maybe.FromJust(); | |
| 241 if (attrs == ABSENT) return factory->undefined_value(); | |
| 242 | |
| 243 DCHECK(!isolate->has_pending_exception()); | |
| 244 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); | |
| 245 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | |
| 246 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | |
| 247 | |
| 248 bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR && | |
| 249 it.GetAccessors()->IsAccessorPair(); | |
| 250 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair)); | |
| 251 | |
| 252 if (is_accessor_pair) { | |
| 253 Handle<AccessorPair> accessors = | |
| 254 Handle<AccessorPair>::cast(it.GetAccessors()); | |
| 255 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | |
| 256 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | |
| 257 elms->set(GETTER_INDEX, *getter); | |
| 258 elms->set(SETTER_INDEX, *setter); | |
| 259 } else { | |
| 260 Handle<Object> value; | |
| 261 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it), | |
| 262 Object); | |
| 263 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); | |
| 264 elms->set(VALUE_INDEX, *value); | |
| 265 } | |
| 266 | |
| 267 return factory->NewJSArrayWithElements(elms); | |
| 268 } | |
| 269 | |
| 270 | |
| 271 // Returns an array with the property description: | |
| 272 // if args[1] is not a property on args[0] | |
| 273 // returns undefined | |
| 274 // if args[1] is a data property on args[0] | |
| 275 // [false, value, Writeable, Enumerable, Configurable] | |
| 276 // if args[1] is an accessor on args[0] | |
| 277 // [true, GetFunction, SetFunction, Enumerable, Configurable] | |
| 278 RUNTIME_FUNCTION(Runtime_GetOwnProperty) { | |
| 279 HandleScope scope(isolate); | |
| 280 DCHECK(args.length() == 2); | |
| 281 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 282 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | |
| 283 Handle<Object> result; | |
| 284 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 285 GetOwnProperty(isolate, obj, name)); | |
| 286 return *result; | |
| 287 } | |
| 288 | |
| 289 | |
| 290 RUNTIME_FUNCTION(Runtime_PreventExtensions) { | |
| 291 HandleScope scope(isolate); | |
| 292 DCHECK(args.length() == 1); | |
| 293 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 294 Handle<Object> result; | |
| 295 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 296 JSObject::PreventExtensions(obj)); | |
| 297 return *result; | |
| 298 } | |
| 299 | |
| 300 | |
| 301 RUNTIME_FUNCTION(Runtime_IsExtensible) { | |
| 302 SealHandleScope shs(isolate); | |
| 303 DCHECK(args.length() == 1); | |
| 304 CONVERT_ARG_CHECKED(JSObject, obj, 0); | |
| 305 return isolate->heap()->ToBoolean(obj->IsExtensible()); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 RUNTIME_FUNCTION(Runtime_DisableAccessChecks) { | |
| 310 HandleScope scope(isolate); | |
| 311 DCHECK(args.length() == 1); | |
| 312 CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0); | |
| 313 Handle<Map> old_map(object->map()); | |
| 314 bool needs_access_checks = old_map->is_access_check_needed(); | |
| 315 if (needs_access_checks) { | |
| 316 // Copy map so it won't interfere constructor's initial map. | |
| 317 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks"); | |
| 318 new_map->set_is_access_check_needed(false); | |
| 319 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map); | |
| 320 } | |
| 321 return isolate->heap()->ToBoolean(needs_access_checks); | |
| 322 } | |
| 323 | |
| 324 | |
| 325 RUNTIME_FUNCTION(Runtime_EnableAccessChecks) { | |
| 326 HandleScope scope(isolate); | |
| 327 DCHECK(args.length() == 1); | |
| 328 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 329 Handle<Map> old_map(object->map()); | |
| 330 RUNTIME_ASSERT(!old_map->is_access_check_needed()); | |
| 331 // Copy map so it won't interfere constructor's initial map. | |
| 332 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks"); | |
| 333 new_map->set_is_access_check_needed(true); | |
| 334 JSObject::MigrateToMap(object, new_map); | |
| 335 return isolate->heap()->undefined_value(); | |
| 336 } | |
| 337 | |
| 338 | |
| 339 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { | |
| 340 HandleScope scope(isolate); | |
| 341 DCHECK(args.length() == 2); | |
| 342 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 343 CONVERT_SMI_ARG_CHECKED(properties, 1); | |
| 344 // Conservative upper limit to prevent fuzz tests from going OOM. | |
| 345 RUNTIME_ASSERT(properties <= 100000); | |
| 346 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) { | |
| 347 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties, | |
| 348 "OptimizeForAdding"); | |
| 349 } | |
| 350 return *object; | |
| 351 } | |
| 352 | |
| 353 | |
| 354 RUNTIME_FUNCTION(Runtime_ObjectFreeze) { | |
| 355 HandleScope scope(isolate); | |
| 356 DCHECK(args.length() == 1); | |
| 357 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 358 | |
| 359 // %ObjectFreeze is a fast path and these cases are handled elsewhere. | |
| 360 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && | |
| 361 !object->map()->is_observed() && !object->IsJSProxy()); | |
| 362 | |
| 363 Handle<Object> result; | |
| 364 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object)); | |
| 365 return *result; | |
| 366 } | |
| 367 | |
| 368 | |
| 369 RUNTIME_FUNCTION(Runtime_ObjectSeal) { | |
| 370 HandleScope scope(isolate); | |
| 371 DCHECK(args.length() == 1); | |
| 372 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 373 | |
| 374 // %ObjectSeal is a fast path and these cases are handled elsewhere. | |
| 375 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && | |
| 376 !object->map()->is_observed() && !object->IsJSProxy()); | |
| 377 | |
| 378 Handle<Object> result; | |
| 379 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object)); | |
| 380 return *result; | |
| 381 } | |
| 382 | |
| 383 | |
| 384 RUNTIME_FUNCTION(Runtime_GetProperty) { | |
| 385 HandleScope scope(isolate); | |
| 386 DCHECK(args.length() == 2); | |
| 387 | |
| 388 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); | |
| 389 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 390 Handle<Object> result; | |
| 391 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 392 isolate, result, Runtime::GetObjectProperty(isolate, object, key)); | |
| 393 return *result; | |
| 394 } | |
| 395 | |
| 396 | |
| 397 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements( | 87 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements( |
| 398 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) { | 88 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) { |
| 399 HandleScope scope(isolate); | 89 HandleScope scope(isolate); |
| 400 if (!object->IsJSObject()) { | 90 if (!object->IsJSObject()) { |
| 401 isolate->ThrowIllegalOperation(); | 91 isolate->ThrowIllegalOperation(); |
| 402 return MaybeHandle<Object>(); | 92 return MaybeHandle<Object>(); |
| 403 } | 93 } |
| 404 ElementsKind from_kind = | 94 ElementsKind from_kind = |
| 405 Handle<JSObject>::cast(object)->map()->elements_kind(); | 95 Handle<JSObject>::cast(object)->map()->elements_kind(); |
| 406 if (Map::IsValidElementsTransition(from_kind, to_kind)) { | 96 if (Map::IsValidElementsTransition(from_kind, to_kind)) { |
| 407 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); | 97 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); |
| 408 return object; | 98 return object; |
| 409 } | 99 } |
| 410 isolate->ThrowIllegalOperation(); | 100 isolate->ThrowIllegalOperation(); |
| 411 return MaybeHandle<Object>(); | 101 return MaybeHandle<Object>(); |
| 412 } | 102 } |
| 413 | 103 |
| 414 | 104 |
| 415 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. | 105 MaybeHandle<Object> Runtime::KeyedGetObjectProperty( |
| 416 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { | 106 Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj, |
| 417 HandleScope scope(isolate); | 107 LanguageMode language_mode) { |
| 418 DCHECK(args.length() == 2); | |
| 419 | |
| 420 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); | |
| 421 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); | |
| 422 | |
| 423 // Fast cases for getting named properties of the receiver JSObject | 108 // Fast cases for getting named properties of the receiver JSObject |
| 424 // itself. | 109 // itself. |
| 425 // | 110 // |
| 426 // The global proxy objects has to be excluded since LookupOwn on | 111 // The global proxy objects has to be excluded since LookupOwn on |
| 427 // the global proxy object can return a valid result even though the | 112 // the global proxy object can return a valid result even though the |
| 428 // global proxy object never has properties. This is the case | 113 // global proxy object never has properties. This is the case |
| 429 // because the global proxy object forwards everything to its hidden | 114 // because the global proxy object forwards everything to its hidden |
| 430 // prototype including own lookups. | 115 // prototype including own lookups. |
| 431 // | 116 // |
| 432 // Additionally, we need to make sure that we do not cache results | 117 // Additionally, we need to make sure that we do not cache results |
| 433 // for objects that require access checks. | 118 // for objects that require access checks. |
| 434 if (receiver_obj->IsJSObject()) { | 119 if (receiver_obj->IsJSObject()) { |
| 435 if (!receiver_obj->IsJSGlobalProxy() && | 120 if (!receiver_obj->IsJSGlobalProxy() && |
| 436 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) { | 121 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) { |
| 437 DisallowHeapAllocation no_allocation; | 122 DisallowHeapAllocation no_allocation; |
| 438 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj); | 123 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj); |
| 439 Handle<Name> key = Handle<Name>::cast(key_obj); | 124 Handle<Name> key = Handle<Name>::cast(key_obj); |
| 440 if (receiver->IsGlobalObject()) { | 125 if (receiver->IsGlobalObject()) { |
| 441 // Attempt dictionary lookup. | 126 // Attempt dictionary lookup. |
| 442 GlobalDictionary* dictionary = receiver->global_dictionary(); | 127 GlobalDictionary* dictionary = receiver->global_dictionary(); |
| 443 int entry = dictionary->FindEntry(key); | 128 int entry = dictionary->FindEntry(key); |
| 444 if (entry != GlobalDictionary::kNotFound) { | 129 if (entry != GlobalDictionary::kNotFound) { |
| 445 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 130 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
| 446 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); | 131 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); |
| 447 if (cell->property_details().type() == DATA) { | 132 if (cell->property_details().type() == DATA) { |
| 448 Object* value = cell->value(); | 133 Object* value = cell->value(); |
| 449 if (!value->IsTheHole()) return value; | 134 if (!value->IsTheHole()) return Handle<Object>(value, isolate); |
| 450 // If value is the hole (meaning, absent) do the general lookup. | 135 // If value is the hole (meaning, absent) do the general lookup. |
| 451 } | 136 } |
| 452 } | 137 } |
| 453 } else if (!receiver->HasFastProperties()) { | 138 } else if (!receiver->HasFastProperties()) { |
| 454 // Attempt dictionary lookup. | 139 // Attempt dictionary lookup. |
| 455 NameDictionary* dictionary = receiver->property_dictionary(); | 140 NameDictionary* dictionary = receiver->property_dictionary(); |
| 456 int entry = dictionary->FindEntry(key); | 141 int entry = dictionary->FindEntry(key); |
| 457 if ((entry != NameDictionary::kNotFound) && | 142 if ((entry != NameDictionary::kNotFound) && |
| 458 (dictionary->DetailsAt(entry).type() == DATA)) { | 143 (dictionary->DetailsAt(entry).type() == DATA)) { |
| 459 Object* value = dictionary->ValueAt(entry); | 144 Object* value = dictionary->ValueAt(entry); |
| 460 return value; | 145 return Handle<Object>(value, isolate); |
| 461 } | 146 } |
| 462 } | 147 } |
| 463 } else if (key_obj->IsSmi()) { | 148 } else if (key_obj->IsSmi()) { |
| 464 // JSObject without a name key. If the key is a Smi, check for a | 149 // JSObject without a name key. If the key is a Smi, check for a |
| 465 // definite out-of-bounds access to elements, which is a strong indicator | 150 // definite out-of-bounds access to elements, which is a strong indicator |
| 466 // that subsequent accesses will also call the runtime. Proactively | 151 // that subsequent accesses will also call the runtime. Proactively |
| 467 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of | 152 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of |
| 468 // doubles for those future calls in the case that the elements would | 153 // doubles for those future calls in the case that the elements would |
| 469 // become FAST_DOUBLE_ELEMENTS. | 154 // become FAST_DOUBLE_ELEMENTS. |
| 470 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj); | 155 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj); |
| 471 ElementsKind elements_kind = js_object->GetElementsKind(); | 156 ElementsKind elements_kind = js_object->GetElementsKind(); |
| 472 if (IsFastDoubleElementsKind(elements_kind)) { | 157 if (IsFastDoubleElementsKind(elements_kind)) { |
| 473 Handle<Smi> key = Handle<Smi>::cast(key_obj); | 158 Handle<Smi> key = Handle<Smi>::cast(key_obj); |
| 474 if (key->value() >= js_object->elements()->length()) { | 159 if (key->value() >= js_object->elements()->length()) { |
| 475 if (IsFastHoleyElementsKind(elements_kind)) { | 160 if (IsFastHoleyElementsKind(elements_kind)) { |
| 476 elements_kind = FAST_HOLEY_ELEMENTS; | 161 elements_kind = FAST_HOLEY_ELEMENTS; |
| 477 } else { | 162 } else { |
| 478 elements_kind = FAST_ELEMENTS; | 163 elements_kind = FAST_ELEMENTS; |
| 479 } | 164 } |
| 480 RETURN_FAILURE_ON_EXCEPTION( | 165 RETURN_ON_EXCEPTION( |
| 481 isolate, TransitionElements(js_object, elements_kind, isolate)); | 166 isolate, TransitionElements(js_object, elements_kind, isolate), |
| 167 Object); |
| 482 } | 168 } |
| 483 } else { | 169 } else { |
| 484 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || | 170 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || |
| 485 !IsFastElementsKind(elements_kind)); | 171 !IsFastElementsKind(elements_kind)); |
| 486 } | 172 } |
| 487 } | 173 } |
| 488 } else if (receiver_obj->IsString() && key_obj->IsSmi()) { | 174 } else if (receiver_obj->IsString() && key_obj->IsSmi()) { |
| 489 // Fast case for string indexing using [] with a smi index. | 175 // Fast case for string indexing using [] with a smi index. |
| 490 Handle<String> str = Handle<String>::cast(receiver_obj); | 176 Handle<String> str = Handle<String>::cast(receiver_obj); |
| 491 int index = args.smi_at(1); | 177 int index = Handle<Smi>::cast(key_obj)->value(); |
| 492 if (index >= 0 && index < str->length()) { | 178 if (index >= 0 && index < str->length()) { |
| 493 return *GetCharAt(str, index); | 179 return GetCharAt(str, index); |
| 494 } | 180 } |
| 495 } | 181 } |
| 496 | 182 |
| 497 // Fall back to GetObjectProperty. | 183 // Fall back to GetObjectProperty. |
| 184 return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode); |
| 185 } |
| 186 |
| 187 |
| 188 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, |
| 189 Handle<Object> object, |
| 190 Handle<Object> key, |
| 191 Handle<Object> value, |
| 192 LanguageMode language_mode) { |
| 193 if (object->IsUndefined() || object->IsNull()) { |
| 194 THROW_NEW_ERROR( |
| 195 isolate, |
| 196 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), |
| 197 Object); |
| 198 } |
| 199 |
| 200 // Check if the given key is an array index. |
| 201 uint32_t index = 0; |
| 202 if (key->ToArrayIndex(&index)) { |
| 203 // TODO(verwaest): Support other objects as well. |
| 204 if (!object->IsJSReceiver()) return value; |
| 205 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, |
| 206 value, language_mode); |
| 207 } |
| 208 |
| 209 Handle<Name> name; |
| 210 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); |
| 211 |
| 212 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); |
| 213 // TODO(verwaest): Support other objects as well. |
| 214 if (it.IsElement() && !object->IsJSReceiver()) return value; |
| 215 return Object::SetProperty(&it, value, language_mode, |
| 216 Object::MAY_BE_STORE_FROM_KEYED); |
| 217 } |
| 218 |
| 219 |
| 220 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, |
| 221 Handle<Object> obj) { |
| 222 // We don't expect access checks to be needed on JSProxy objects. |
| 223 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
| 224 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
| 225 do { |
| 226 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && |
| 227 !isolate->MayAccess( |
| 228 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) { |
| 229 isolate->ReportFailedAccessCheck( |
| 230 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
| 231 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 232 return isolate->factory()->undefined_value(); |
| 233 } |
| 234 iter.AdvanceIgnoringProxies(); |
| 235 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| 236 return PrototypeIterator::GetCurrent(iter); |
| 237 } |
| 238 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); |
| 239 return PrototypeIterator::GetCurrent(iter); |
| 240 } |
| 241 |
| 242 |
| 243 RUNTIME_FUNCTION(Runtime_GetPrototype) { |
| 244 HandleScope scope(isolate); |
| 245 DCHECK(args.length() == 1); |
| 246 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); |
| 247 Handle<Object> result; |
| 248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 249 Runtime::GetPrototype(isolate, obj)); |
| 250 return *result; |
| 251 } |
| 252 |
| 253 |
| 254 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { |
| 255 HandleScope scope(isolate); |
| 256 DCHECK(args.length() == 2); |
| 257 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 258 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); |
| 259 DCHECK(!obj->IsAccessCheckNeeded()); |
| 260 DCHECK(!obj->map()->is_observed()); |
| 261 Handle<Object> result; |
| 262 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 263 isolate, result, JSObject::SetPrototype(obj, prototype, false)); |
| 264 return *result; |
| 265 } |
| 266 |
| 267 |
| 268 RUNTIME_FUNCTION(Runtime_SetPrototype) { |
| 269 HandleScope scope(isolate); |
| 270 DCHECK(args.length() == 2); |
| 271 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 272 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); |
| 273 if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) { |
| 274 isolate->ReportFailedAccessCheck(obj); |
| 275 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 276 return isolate->heap()->undefined_value(); |
| 277 } |
| 278 if (obj->map()->is_observed()) { |
| 279 Handle<Object> old_value = |
| 280 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); |
| 281 Handle<Object> result; |
| 282 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 283 isolate, result, JSObject::SetPrototype(obj, prototype, true)); |
| 284 |
| 285 Handle<Object> new_value = |
| 286 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); |
| 287 if (!new_value->SameValue(*old_value)) { |
| 288 RETURN_FAILURE_ON_EXCEPTION( |
| 289 isolate, JSObject::EnqueueChangeRecord( |
| 290 obj, "setPrototype", isolate->factory()->proto_string(), |
| 291 old_value)); |
| 292 } |
| 293 return *result; |
| 294 } |
| 295 Handle<Object> result; |
| 296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 297 isolate, result, JSObject::SetPrototype(obj, prototype, true)); |
| 298 return *result; |
| 299 } |
| 300 |
| 301 |
| 302 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) { |
| 303 HandleScope shs(isolate); |
| 304 DCHECK(args.length() == 2); |
| 305 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). |
| 306 CONVERT_ARG_HANDLE_CHECKED(Object, O, 0); |
| 307 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); |
| 308 PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER); |
| 309 while (true) { |
| 310 iter.AdvanceIgnoringProxies(); |
| 311 if (iter.IsAtEnd()) return isolate->heap()->false_value(); |
| 312 if (iter.IsAtEnd(O)) return isolate->heap()->true_value(); |
| 313 } |
| 314 } |
| 315 |
| 316 |
| 317 // Enumerator used as indices into the array returned from GetOwnProperty |
| 318 enum PropertyDescriptorIndices { |
| 319 IS_ACCESSOR_INDEX, |
| 320 VALUE_INDEX, |
| 321 GETTER_INDEX, |
| 322 SETTER_INDEX, |
| 323 WRITABLE_INDEX, |
| 324 ENUMERABLE_INDEX, |
| 325 CONFIGURABLE_INDEX, |
| 326 DESCRIPTOR_SIZE |
| 327 }; |
| 328 |
| 329 |
| 330 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, |
| 331 Handle<JSObject> obj, |
| 332 Handle<Name> name) { |
| 333 Heap* heap = isolate->heap(); |
| 334 Factory* factory = isolate->factory(); |
| 335 |
| 336 PropertyAttributes attrs; |
| 337 // Get attributes. |
| 338 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name, |
| 339 LookupIterator::HIDDEN); |
| 340 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it); |
| 341 |
| 342 if (!maybe.IsJust()) return MaybeHandle<Object>(); |
| 343 attrs = maybe.FromJust(); |
| 344 if (attrs == ABSENT) return factory->undefined_value(); |
| 345 |
| 346 DCHECK(!isolate->has_pending_exception()); |
| 347 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); |
| 348 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
| 349 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
| 350 |
| 351 bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR && |
| 352 it.GetAccessors()->IsAccessorPair(); |
| 353 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair)); |
| 354 |
| 355 if (is_accessor_pair) { |
| 356 Handle<AccessorPair> accessors = |
| 357 Handle<AccessorPair>::cast(it.GetAccessors()); |
| 358 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); |
| 359 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); |
| 360 elms->set(GETTER_INDEX, *getter); |
| 361 elms->set(SETTER_INDEX, *setter); |
| 362 } else { |
| 363 Handle<Object> value; |
| 364 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it), |
| 365 Object); |
| 366 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
| 367 elms->set(VALUE_INDEX, *value); |
| 368 } |
| 369 |
| 370 return factory->NewJSArrayWithElements(elms); |
| 371 } |
| 372 |
| 373 |
| 374 // Returns an array with the property description: |
| 375 // if args[1] is not a property on args[0] |
| 376 // returns undefined |
| 377 // if args[1] is a data property on args[0] |
| 378 // [false, value, Writeable, Enumerable, Configurable] |
| 379 // if args[1] is an accessor on args[0] |
| 380 // [true, GetFunction, SetFunction, Enumerable, Configurable] |
| 381 RUNTIME_FUNCTION(Runtime_GetOwnProperty) { |
| 382 HandleScope scope(isolate); |
| 383 DCHECK(args.length() == 2); |
| 384 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 385 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
| 386 Handle<Object> result; |
| 387 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 388 GetOwnProperty(isolate, obj, name)); |
| 389 return *result; |
| 390 } |
| 391 |
| 392 |
| 393 RUNTIME_FUNCTION(Runtime_PreventExtensions) { |
| 394 HandleScope scope(isolate); |
| 395 DCHECK(args.length() == 1); |
| 396 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 397 Handle<Object> result; |
| 398 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 399 JSObject::PreventExtensions(obj)); |
| 400 return *result; |
| 401 } |
| 402 |
| 403 |
| 404 RUNTIME_FUNCTION(Runtime_IsExtensible) { |
| 405 SealHandleScope shs(isolate); |
| 406 DCHECK(args.length() == 1); |
| 407 CONVERT_ARG_CHECKED(JSObject, obj, 0); |
| 408 return isolate->heap()->ToBoolean(obj->IsExtensible()); |
| 409 } |
| 410 |
| 411 |
| 412 RUNTIME_FUNCTION(Runtime_DisableAccessChecks) { |
| 413 HandleScope scope(isolate); |
| 414 DCHECK(args.length() == 1); |
| 415 CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0); |
| 416 Handle<Map> old_map(object->map()); |
| 417 bool needs_access_checks = old_map->is_access_check_needed(); |
| 418 if (needs_access_checks) { |
| 419 // Copy map so it won't interfere constructor's initial map. |
| 420 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks"); |
| 421 new_map->set_is_access_check_needed(false); |
| 422 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map); |
| 423 } |
| 424 return isolate->heap()->ToBoolean(needs_access_checks); |
| 425 } |
| 426 |
| 427 |
| 428 RUNTIME_FUNCTION(Runtime_EnableAccessChecks) { |
| 429 HandleScope scope(isolate); |
| 430 DCHECK(args.length() == 1); |
| 431 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 432 Handle<Map> old_map(object->map()); |
| 433 RUNTIME_ASSERT(!old_map->is_access_check_needed()); |
| 434 // Copy map so it won't interfere constructor's initial map. |
| 435 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks"); |
| 436 new_map->set_is_access_check_needed(true); |
| 437 JSObject::MigrateToMap(object, new_map); |
| 438 return isolate->heap()->undefined_value(); |
| 439 } |
| 440 |
| 441 |
| 442 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { |
| 443 HandleScope scope(isolate); |
| 444 DCHECK(args.length() == 2); |
| 445 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 446 CONVERT_SMI_ARG_CHECKED(properties, 1); |
| 447 // Conservative upper limit to prevent fuzz tests from going OOM. |
| 448 RUNTIME_ASSERT(properties <= 100000); |
| 449 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) { |
| 450 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties, |
| 451 "OptimizeForAdding"); |
| 452 } |
| 453 return *object; |
| 454 } |
| 455 |
| 456 |
| 457 RUNTIME_FUNCTION(Runtime_ObjectFreeze) { |
| 458 HandleScope scope(isolate); |
| 459 DCHECK(args.length() == 1); |
| 460 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 461 |
| 462 // %ObjectFreeze is a fast path and these cases are handled elsewhere. |
| 463 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && |
| 464 !object->map()->is_observed() && !object->IsJSProxy()); |
| 465 |
| 466 Handle<Object> result; |
| 467 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object)); |
| 468 return *result; |
| 469 } |
| 470 |
| 471 |
| 472 RUNTIME_FUNCTION(Runtime_ObjectSeal) { |
| 473 HandleScope scope(isolate); |
| 474 DCHECK(args.length() == 1); |
| 475 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 476 |
| 477 // %ObjectSeal is a fast path and these cases are handled elsewhere. |
| 478 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && |
| 479 !object->map()->is_observed() && !object->IsJSProxy()); |
| 480 |
| 481 Handle<Object> result; |
| 482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object)); |
| 483 return *result; |
| 484 } |
| 485 |
| 486 |
| 487 RUNTIME_FUNCTION(Runtime_GetProperty) { |
| 488 HandleScope scope(isolate); |
| 489 DCHECK(args.length() == 3); |
| 490 |
| 491 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); |
| 492 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); |
| 493 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); |
| 494 |
| 498 Handle<Object> result; | 495 Handle<Object> result; |
| 499 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 500 isolate, result, | 497 isolate, result, |
| 501 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); | 498 Runtime::GetObjectProperty(isolate, object, key, language_mode)); |
| 502 return *result; | 499 return *result; |
| 503 } | 500 } |
| 504 | 501 |
| 502 |
| 503 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { |
| 504 HandleScope scope(isolate); |
| 505 DCHECK(args.length() == 3); |
| 506 |
| 507 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); |
| 508 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); |
| 509 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); |
| 510 |
| 511 Handle<Object> result; |
| 512 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 513 isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver_obj, |
| 514 key_obj, language_mode)); |
| 515 return *result; |
| 516 } |
| 517 |
| 505 | 518 |
| 506 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { | 519 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { |
| 507 HandleScope scope(isolate); | 520 HandleScope scope(isolate); |
| 508 RUNTIME_ASSERT(args.length() == 4); | 521 RUNTIME_ASSERT(args.length() == 4); |
| 509 | 522 |
| 510 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 523 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 511 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 524 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
| 512 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 525 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 513 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 526 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 514 | 527 |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1437 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 1425 | 1438 |
| 1426 RETURN_FAILURE_ON_EXCEPTION( | 1439 RETURN_FAILURE_ON_EXCEPTION( |
| 1427 isolate, | 1440 isolate, |
| 1428 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), | 1441 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), |
| 1429 setter, attrs)); | 1442 setter, attrs)); |
| 1430 return isolate->heap()->undefined_value(); | 1443 return isolate->heap()->undefined_value(); |
| 1431 } | 1444 } |
| 1432 } // namespace internal | 1445 } // namespace internal |
| 1433 } // namespace v8 | 1446 } // namespace v8 |
| OLD | NEW |