OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1449 ASSERT(args.length() == 1); | 1449 ASSERT(args.length() == 1); |
1450 CONVERT_ARG_CHECKED(Object, obj, 0); | 1450 CONVERT_ARG_CHECKED(Object, obj, 0); |
1451 // We don't expect access checks to be needed on JSProxy objects. | 1451 // We don't expect access checks to be needed on JSProxy objects. |
1452 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | 1452 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
1453 do { | 1453 do { |
1454 if (obj->IsAccessCheckNeeded() && | 1454 if (obj->IsAccessCheckNeeded() && |
1455 !isolate->MayNamedAccess(JSObject::cast(obj), | 1455 !isolate->MayNamedAccess(JSObject::cast(obj), |
1456 isolate->heap()->proto_string(), | 1456 isolate->heap()->proto_string(), |
1457 v8::ACCESS_GET)) { | 1457 v8::ACCESS_GET)) { |
1458 isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET); | 1458 isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET); |
| 1459 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
1459 return isolate->heap()->undefined_value(); | 1460 return isolate->heap()->undefined_value(); |
1460 } | 1461 } |
1461 obj = obj->GetPrototype(isolate); | 1462 obj = obj->GetPrototype(isolate); |
1462 } while (obj->IsJSObject() && | 1463 } while (obj->IsJSObject() && |
1463 JSObject::cast(obj)->map()->is_hidden_prototype()); | 1464 JSObject::cast(obj)->map()->is_hidden_prototype()); |
1464 return obj; | 1465 return obj; |
1465 } | 1466 } |
1466 | 1467 |
1467 | 1468 |
1468 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate, | 1469 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1553 } | 1554 } |
1554 | 1555 |
1555 | 1556 |
1556 enum AccessCheckResult { | 1557 enum AccessCheckResult { |
1557 ACCESS_FORBIDDEN, | 1558 ACCESS_FORBIDDEN, |
1558 ACCESS_ALLOWED, | 1559 ACCESS_ALLOWED, |
1559 ACCESS_ABSENT | 1560 ACCESS_ABSENT |
1560 }; | 1561 }; |
1561 | 1562 |
1562 | 1563 |
1563 static AccessCheckResult CheckElementAccess( | |
1564 JSObject* obj, | |
1565 uint32_t index, | |
1566 v8::AccessType access_type) { | |
1567 // TODO(1095): we should traverse hidden prototype hierachy as well. | |
1568 if (CheckGenericAccess( | |
1569 obj, obj, index, access_type, &Isolate::MayIndexedAccess)) { | |
1570 return ACCESS_ALLOWED; | |
1571 } | |
1572 | |
1573 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); | |
1574 return ACCESS_FORBIDDEN; | |
1575 } | |
1576 | |
1577 | |
1578 static AccessCheckResult CheckPropertyAccess( | 1564 static AccessCheckResult CheckPropertyAccess( |
1579 JSObject* obj, | 1565 JSObject* obj, |
1580 Name* name, | 1566 Name* name, |
1581 v8::AccessType access_type) { | 1567 v8::AccessType access_type) { |
1582 uint32_t index; | 1568 uint32_t index; |
1583 if (name->AsArrayIndex(&index)) { | 1569 if (name->AsArrayIndex(&index)) { |
1584 return CheckElementAccess(obj, index, access_type); | 1570 // TODO(1095): we should traverse hidden prototype hierachy as well. |
| 1571 if (CheckGenericAccess( |
| 1572 obj, obj, index, access_type, &Isolate::MayIndexedAccess)) { |
| 1573 return ACCESS_ALLOWED; |
| 1574 } |
| 1575 |
| 1576 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); |
| 1577 return ACCESS_FORBIDDEN; |
1585 } | 1578 } |
1586 | 1579 |
1587 LookupResult lookup(obj->GetIsolate()); | 1580 LookupResult lookup(obj->GetIsolate()); |
1588 obj->LocalLookup(name, &lookup, true); | 1581 obj->LocalLookup(name, &lookup, true); |
1589 | 1582 |
1590 if (!lookup.IsProperty()) return ACCESS_ABSENT; | 1583 if (!lookup.IsProperty()) return ACCESS_ABSENT; |
1591 if (CheckGenericAccess<Object*>( | 1584 if (CheckGenericAccess<Object*>( |
1592 obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) { | 1585 obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) { |
1593 return ACCESS_ALLOWED; | 1586 return ACCESS_ALLOWED; |
1594 } | 1587 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 DESCRIPTOR_SIZE | 1627 DESCRIPTOR_SIZE |
1635 }; | 1628 }; |
1636 | 1629 |
1637 | 1630 |
1638 static MaybeObject* GetOwnProperty(Isolate* isolate, | 1631 static MaybeObject* GetOwnProperty(Isolate* isolate, |
1639 Handle<JSObject> obj, | 1632 Handle<JSObject> obj, |
1640 Handle<Name> name) { | 1633 Handle<Name> name) { |
1641 Heap* heap = isolate->heap(); | 1634 Heap* heap = isolate->heap(); |
1642 // Due to some WebKit tests, we want to make sure that we do not log | 1635 // Due to some WebKit tests, we want to make sure that we do not log |
1643 // more than one access failure here. | 1636 // more than one access failure here. |
1644 switch (CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS)) { | 1637 AccessCheckResult access_check_result = |
| 1638 CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS); |
| 1639 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1640 switch (access_check_result) { |
1645 case ACCESS_FORBIDDEN: return heap->false_value(); | 1641 case ACCESS_FORBIDDEN: return heap->false_value(); |
1646 case ACCESS_ALLOWED: break; | 1642 case ACCESS_ALLOWED: break; |
1647 case ACCESS_ABSENT: return heap->undefined_value(); | 1643 case ACCESS_ABSENT: return heap->undefined_value(); |
1648 } | 1644 } |
1649 | 1645 |
1650 PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name); | 1646 PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name); |
1651 if (attrs == ABSENT) return heap->undefined_value(); | 1647 if (attrs == ABSENT) { |
| 1648 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1649 return heap->undefined_value(); |
| 1650 } |
| 1651 ASSERT(!isolate->has_scheduled_exception()); |
1652 AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name); | 1652 AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name); |
1653 Handle<AccessorPair> accessors(raw_accessors, isolate); | 1653 Handle<AccessorPair> accessors(raw_accessors, isolate); |
1654 | 1654 |
1655 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); | 1655 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); |
1656 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | 1656 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
1657 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | 1657 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
1658 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL)); | 1658 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL)); |
1659 | 1659 |
1660 if (raw_accessors == NULL) { | 1660 if (raw_accessors == NULL) { |
1661 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); | 1661 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
1662 // GetProperty does access check. | 1662 // GetProperty does access check. |
1663 Handle<Object> value = GetProperty(isolate, obj, name); | 1663 Handle<Object> value = GetProperty(isolate, obj, name); |
1664 RETURN_IF_EMPTY_HANDLE(isolate, value); | 1664 RETURN_IF_EMPTY_HANDLE(isolate, value); |
1665 elms->set(VALUE_INDEX, *value); | 1665 elms->set(VALUE_INDEX, *value); |
1666 } else { | 1666 } else { |
1667 // Access checks are performed for both accessors separately. | 1667 // Access checks are performed for both accessors separately. |
1668 // When they fail, the respective field is not set in the descriptor. | 1668 // When they fail, the respective field is not set in the descriptor. |
1669 Object* getter = accessors->GetComponent(ACCESSOR_GETTER); | 1669 Object* getter = accessors->GetComponent(ACCESSOR_GETTER); |
1670 Object* setter = accessors->GetComponent(ACCESSOR_SETTER); | 1670 Object* setter = accessors->GetComponent(ACCESSOR_SETTER); |
1671 if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) { | 1671 if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) { |
| 1672 ASSERT(!isolate->has_scheduled_exception()); |
1672 elms->set(GETTER_INDEX, getter); | 1673 elms->set(GETTER_INDEX, getter); |
| 1674 } else { |
| 1675 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
1673 } | 1676 } |
1674 if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) { | 1677 if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) { |
| 1678 ASSERT(!isolate->has_scheduled_exception()); |
1675 elms->set(SETTER_INDEX, setter); | 1679 elms->set(SETTER_INDEX, setter); |
| 1680 } else { |
| 1681 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
1676 } | 1682 } |
1677 } | 1683 } |
1678 | 1684 |
1679 return *isolate->factory()->NewJSArrayWithElements(elms); | 1685 return *isolate->factory()->NewJSArrayWithElements(elms); |
1680 } | 1686 } |
1681 | 1687 |
1682 | 1688 |
1683 // Returns an array with the property description: | 1689 // Returns an array with the property description: |
1684 // if args[1] is not a property on args[0] | 1690 // if args[1] is not a property on args[0] |
1685 // returns undefined | 1691 // returns undefined |
(...skipping 3120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4806 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); | 4812 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); |
4807 RUNTIME_ASSERT(IsValidAccessor(getter)); | 4813 RUNTIME_ASSERT(IsValidAccessor(getter)); |
4808 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); | 4814 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); |
4809 RUNTIME_ASSERT(IsValidAccessor(setter)); | 4815 RUNTIME_ASSERT(IsValidAccessor(setter)); |
4810 CONVERT_SMI_ARG_CHECKED(unchecked, 4); | 4816 CONVERT_SMI_ARG_CHECKED(unchecked, 4); |
4811 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 4817 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
4812 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 4818 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
4813 | 4819 |
4814 bool fast = obj->HasFastProperties(); | 4820 bool fast = obj->HasFastProperties(); |
4815 JSObject::DefineAccessor(obj, name, getter, setter, attr); | 4821 JSObject::DefineAccessor(obj, name, getter, setter, attr); |
| 4822 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
4816 if (fast) JSObject::TransformToFastProperties(obj, 0); | 4823 if (fast) JSObject::TransformToFastProperties(obj, 0); |
4817 return isolate->heap()->undefined_value(); | 4824 return isolate->heap()->undefined_value(); |
4818 } | 4825 } |
4819 | 4826 |
4820 | 4827 |
4821 // Implements part of 8.12.9 DefineOwnProperty. | 4828 // Implements part of 8.12.9 DefineOwnProperty. |
4822 // There are 3 cases that lead here: | 4829 // There are 3 cases that lead here: |
4823 // Step 4a - define a new data property. | 4830 // Step 4a - define a new data property. |
4824 // Steps 9b & 12 - replace an existing accessor property with a data property. | 4831 // Steps 9b & 12 - replace an existing accessor property with a data property. |
4825 // Step 12 - update an existing data property with a data or generic | 4832 // Step 12 - update an existing data property with a data or generic |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5332 | 5339 |
5333 CONVERT_ARG_CHECKED(JSReceiver, object, 0); | 5340 CONVERT_ARG_CHECKED(JSReceiver, object, 0); |
5334 CONVERT_ARG_CHECKED(Name, key, 1); | 5341 CONVERT_ARG_CHECKED(Name, key, 1); |
5335 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2); | 5342 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2); |
5336 return object->DeleteProperty(key, (strict_mode == kStrictMode) | 5343 return object->DeleteProperty(key, (strict_mode == kStrictMode) |
5337 ? JSReceiver::STRICT_DELETION | 5344 ? JSReceiver::STRICT_DELETION |
5338 : JSReceiver::NORMAL_DELETION); | 5345 : JSReceiver::NORMAL_DELETION); |
5339 } | 5346 } |
5340 | 5347 |
5341 | 5348 |
5342 static Object* HasLocalPropertyImplementation(Isolate* isolate, | 5349 static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate, |
5343 Handle<JSObject> object, | 5350 Handle<JSObject> object, |
5344 Handle<Name> key) { | 5351 Handle<Name> key) { |
5345 if (object->HasLocalProperty(*key)) return isolate->heap()->true_value(); | 5352 if (object->HasLocalProperty(*key)) return isolate->heap()->true_value(); |
5346 // Handle hidden prototypes. If there's a hidden prototype above this thing | 5353 // Handle hidden prototypes. If there's a hidden prototype above this thing |
5347 // then we have to check it for properties, because they are supposed to | 5354 // then we have to check it for properties, because they are supposed to |
5348 // look like they are on this object. | 5355 // look like they are on this object. |
5349 Handle<Object> proto(object->GetPrototype(), isolate); | 5356 Handle<Object> proto(object->GetPrototype(), isolate); |
5350 if (proto->IsJSObject() && | 5357 if (proto->IsJSObject() && |
5351 Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) { | 5358 Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) { |
5352 return HasLocalPropertyImplementation(isolate, | 5359 return HasLocalPropertyImplementation(isolate, |
5353 Handle<JSObject>::cast(proto), | 5360 Handle<JSObject>::cast(proto), |
5354 key); | 5361 key); |
5355 } | 5362 } |
| 5363 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5356 return isolate->heap()->false_value(); | 5364 return isolate->heap()->false_value(); |
5357 } | 5365 } |
5358 | 5366 |
5359 | 5367 |
5360 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) { | 5368 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) { |
5361 SealHandleScope shs(isolate); | 5369 SealHandleScope shs(isolate); |
5362 ASSERT(args.length() == 2); | 5370 ASSERT(args.length() == 2); |
5363 CONVERT_ARG_CHECKED(Name, key, 1); | 5371 CONVERT_ARG_CHECKED(Name, key, 1); |
5364 | 5372 |
5365 uint32_t index; | 5373 uint32_t index; |
5366 const bool key_is_array_index = key->AsArrayIndex(&index); | 5374 const bool key_is_array_index = key->AsArrayIndex(&index); |
5367 | 5375 |
5368 Object* obj = args[0]; | 5376 Object* obj = args[0]; |
5369 // Only JS objects can have properties. | 5377 // Only JS objects can have properties. |
5370 if (obj->IsJSObject()) { | 5378 if (obj->IsJSObject()) { |
5371 JSObject* object = JSObject::cast(obj); | 5379 JSObject* object = JSObject::cast(obj); |
5372 // Fast case: either the key is a real named property or it is not | 5380 // Fast case: either the key is a real named property or it is not |
5373 // an array index and there are no interceptors or hidden | 5381 // an array index and there are no interceptors or hidden |
5374 // prototypes. | 5382 // prototypes. |
5375 if (object->HasRealNamedProperty(isolate, key)) | 5383 if (object->HasRealNamedProperty(isolate, key)) { |
| 5384 ASSERT(!isolate->has_scheduled_exception()); |
5376 return isolate->heap()->true_value(); | 5385 return isolate->heap()->true_value(); |
| 5386 } else { |
| 5387 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 5388 } |
5377 Map* map = object->map(); | 5389 Map* map = object->map(); |
5378 if (!key_is_array_index && | 5390 if (!key_is_array_index && |
5379 !map->has_named_interceptor() && | 5391 !map->has_named_interceptor() && |
5380 !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) { | 5392 !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) { |
5381 return isolate->heap()->false_value(); | 5393 return isolate->heap()->false_value(); |
5382 } | 5394 } |
5383 // Slow case. | 5395 // Slow case. |
5384 HandleScope scope(isolate); | 5396 HandleScope scope(isolate); |
5385 return HasLocalPropertyImplementation(isolate, | 5397 return HasLocalPropertyImplementation(isolate, |
5386 Handle<JSObject>(object), | 5398 Handle<JSObject>(object), |
5387 Handle<Name>(key)); | 5399 Handle<Name>(key)); |
5388 } else if (obj->IsString() && key_is_array_index) { | 5400 } else if (obj->IsString() && key_is_array_index) { |
5389 // Well, there is one exception: Handle [] on strings. | 5401 // Well, there is one exception: Handle [] on strings. |
5390 String* string = String::cast(obj); | 5402 String* string = String::cast(obj); |
5391 if (index < static_cast<uint32_t>(string->length())) { | 5403 if (index < static_cast<uint32_t>(string->length())) { |
5392 return isolate->heap()->true_value(); | 5404 return isolate->heap()->true_value(); |
5393 } | 5405 } |
5394 } | 5406 } |
5395 return isolate->heap()->false_value(); | 5407 return isolate->heap()->false_value(); |
5396 } | 5408 } |
5397 | 5409 |
5398 | 5410 |
5399 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { | 5411 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { |
5400 SealHandleScope shs(isolate); | 5412 SealHandleScope shs(isolate); |
5401 ASSERT(args.length() == 2); | 5413 ASSERT(args.length() == 2); |
5402 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); | 5414 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); |
5403 CONVERT_ARG_CHECKED(Name, key, 1); | 5415 CONVERT_ARG_CHECKED(Name, key, 1); |
5404 | 5416 |
5405 bool result = receiver->HasProperty(key); | 5417 bool result = receiver->HasProperty(key); |
| 5418 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5406 if (isolate->has_pending_exception()) return Failure::Exception(); | 5419 if (isolate->has_pending_exception()) return Failure::Exception(); |
5407 return isolate->heap()->ToBoolean(result); | 5420 return isolate->heap()->ToBoolean(result); |
5408 } | 5421 } |
5409 | 5422 |
5410 | 5423 |
5411 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) { | 5424 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) { |
5412 SealHandleScope shs(isolate); | 5425 SealHandleScope shs(isolate); |
5413 ASSERT(args.length() == 2); | 5426 ASSERT(args.length() == 2); |
5414 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); | 5427 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); |
5415 CONVERT_SMI_ARG_CHECKED(index, 1); | 5428 CONVERT_SMI_ARG_CHECKED(index, 1); |
5416 | 5429 |
5417 bool result = receiver->HasElement(index); | 5430 bool result = receiver->HasElement(index); |
| 5431 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5418 if (isolate->has_pending_exception()) return Failure::Exception(); | 5432 if (isolate->has_pending_exception()) return Failure::Exception(); |
5419 return isolate->heap()->ToBoolean(result); | 5433 return isolate->heap()->ToBoolean(result); |
5420 } | 5434 } |
5421 | 5435 |
5422 | 5436 |
5423 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { | 5437 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { |
5424 SealHandleScope shs(isolate); | 5438 SealHandleScope shs(isolate); |
5425 ASSERT(args.length() == 2); | 5439 ASSERT(args.length() == 2); |
5426 | 5440 |
5427 CONVERT_ARG_CHECKED(JSObject, object, 0); | 5441 CONVERT_ARG_CHECKED(JSObject, object, 0); |
5428 CONVERT_ARG_CHECKED(Name, key, 1); | 5442 CONVERT_ARG_CHECKED(Name, key, 1); |
5429 | 5443 |
5430 PropertyAttributes att = object->GetLocalPropertyAttribute(key); | 5444 PropertyAttributes att = object->GetLocalPropertyAttribute(key); |
5431 return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); | 5445 if (att == ABSENT || (att & DONT_ENUM) != 0) { |
| 5446 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 5447 return isolate->heap()->false_value(); |
| 5448 } |
| 5449 ASSERT(!isolate->has_scheduled_exception()); |
| 5450 return isolate->heap()->true_value(); |
5432 } | 5451 } |
5433 | 5452 |
5434 | 5453 |
5435 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { | 5454 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { |
5436 HandleScope scope(isolate); | 5455 HandleScope scope(isolate); |
5437 ASSERT(args.length() == 1); | 5456 ASSERT(args.length() == 1); |
5438 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 5457 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
5439 bool threw = false; | 5458 bool threw = false; |
5440 Handle<JSArray> result = GetKeysFor(object, &threw); | 5459 Handle<JSArray> result = GetKeysFor(object, &threw); |
5441 if (threw) return Failure::Exception(); | 5460 if (threw) return Failure::Exception(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5499 | 5518 |
5500 // Skip the global proxy as it has no properties and always delegates to the | 5519 // Skip the global proxy as it has no properties and always delegates to the |
5501 // real global object. | 5520 // real global object. |
5502 if (obj->IsJSGlobalProxy()) { | 5521 if (obj->IsJSGlobalProxy()) { |
5503 // Only collect names if access is permitted. | 5522 // Only collect names if access is permitted. |
5504 if (obj->IsAccessCheckNeeded() && | 5523 if (obj->IsAccessCheckNeeded() && |
5505 !isolate->MayNamedAccess(*obj, | 5524 !isolate->MayNamedAccess(*obj, |
5506 isolate->heap()->undefined_value(), | 5525 isolate->heap()->undefined_value(), |
5507 v8::ACCESS_KEYS)) { | 5526 v8::ACCESS_KEYS)) { |
5508 isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS); | 5527 isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS); |
| 5528 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5509 return *isolate->factory()->NewJSArray(0); | 5529 return *isolate->factory()->NewJSArray(0); |
5510 } | 5530 } |
5511 obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype())); | 5531 obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype())); |
5512 } | 5532 } |
5513 | 5533 |
5514 // Find the number of objects making up this. | 5534 // Find the number of objects making up this. |
5515 int length = LocalPrototypeChainLength(*obj); | 5535 int length = LocalPrototypeChainLength(*obj); |
5516 | 5536 |
5517 // Find the number of local properties for each of the objects. | 5537 // Find the number of local properties for each of the objects. |
5518 ScopedVector<int> local_property_count(length); | 5538 ScopedVector<int> local_property_count(length); |
5519 int total_property_count = 0; | 5539 int total_property_count = 0; |
5520 Handle<JSObject> jsproto = obj; | 5540 Handle<JSObject> jsproto = obj; |
5521 for (int i = 0; i < length; i++) { | 5541 for (int i = 0; i < length; i++) { |
5522 // Only collect names if access is permitted. | 5542 // Only collect names if access is permitted. |
5523 if (jsproto->IsAccessCheckNeeded() && | 5543 if (jsproto->IsAccessCheckNeeded() && |
5524 !isolate->MayNamedAccess(*jsproto, | 5544 !isolate->MayNamedAccess(*jsproto, |
5525 isolate->heap()->undefined_value(), | 5545 isolate->heap()->undefined_value(), |
5526 v8::ACCESS_KEYS)) { | 5546 v8::ACCESS_KEYS)) { |
5527 isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS); | 5547 isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS); |
| 5548 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5528 return *isolate->factory()->NewJSArray(0); | 5549 return *isolate->factory()->NewJSArray(0); |
5529 } | 5550 } |
5530 int n; | 5551 int n; |
5531 n = jsproto->NumberOfLocalProperties(filter); | 5552 n = jsproto->NumberOfLocalProperties(filter); |
5532 local_property_count[i] = n; | 5553 local_property_count[i] = n; |
5533 total_property_count += n; | 5554 total_property_count += n; |
5534 if (i < length - 1) { | 5555 if (i < length - 1) { |
5535 jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); | 5556 jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); |
5536 } | 5557 } |
5537 } | 5558 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5644 ASSERT_EQ(args.length(), 1); | 5665 ASSERT_EQ(args.length(), 1); |
5645 CONVERT_ARG_CHECKED(JSObject, raw_object, 0); | 5666 CONVERT_ARG_CHECKED(JSObject, raw_object, 0); |
5646 Handle<JSObject> object(raw_object); | 5667 Handle<JSObject> object(raw_object); |
5647 | 5668 |
5648 if (object->IsJSGlobalProxy()) { | 5669 if (object->IsJSGlobalProxy()) { |
5649 // Do access checks before going to the global object. | 5670 // Do access checks before going to the global object. |
5650 if (object->IsAccessCheckNeeded() && | 5671 if (object->IsAccessCheckNeeded() && |
5651 !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(), | 5672 !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(), |
5652 v8::ACCESS_KEYS)) { | 5673 v8::ACCESS_KEYS)) { |
5653 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); | 5674 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
| 5675 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
5654 return *isolate->factory()->NewJSArray(0); | 5676 return *isolate->factory()->NewJSArray(0); |
5655 } | 5677 } |
5656 | 5678 |
5657 Handle<Object> proto(object->GetPrototype(), isolate); | 5679 Handle<Object> proto(object->GetPrototype(), isolate); |
5658 // If proxy is detached we simply return an empty array. | 5680 // If proxy is detached we simply return an empty array. |
5659 if (proto->IsNull()) return *isolate->factory()->NewJSArray(0); | 5681 if (proto->IsNull()) return *isolate->factory()->NewJSArray(0); |
5660 object = Handle<JSObject>::cast(proto); | 5682 object = Handle<JSObject>::cast(proto); |
5661 } | 5683 } |
5662 | 5684 |
5663 bool threw = false; | 5685 bool threw = false; |
(...skipping 8352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14016 // Handle last resort GC and make sure to allow future allocations | 14038 // Handle last resort GC and make sure to allow future allocations |
14017 // to grow the heap without causing GCs (if possible). | 14039 // to grow the heap without causing GCs (if possible). |
14018 isolate->counters()->gc_last_resort_from_js()->Increment(); | 14040 isolate->counters()->gc_last_resort_from_js()->Increment(); |
14019 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 14041 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
14020 "Runtime::PerformGC"); | 14042 "Runtime::PerformGC"); |
14021 } | 14043 } |
14022 } | 14044 } |
14023 | 14045 |
14024 | 14046 |
14025 } } // namespace v8::internal | 14047 } } // namespace v8::internal |
OLD | NEW |