OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 5735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5746 isolate, content, | 5746 isolate, content, |
5747 JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); | 5747 JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); |
5748 | 5748 |
5749 // Test again, since cache may have been built by preceding call. | 5749 // Test again, since cache may have been built by preceding call. |
5750 if (object->IsSimpleEnum()) return object->map(); | 5750 if (object->IsSimpleEnum()) return object->map(); |
5751 | 5751 |
5752 return *content; | 5752 return *content; |
5753 } | 5753 } |
5754 | 5754 |
5755 | 5755 |
| 5756 // Find the length of the prototype chain that is to be handled as one. If a |
| 5757 // prototype object is hidden it is to be viewed as part of the the object it |
| 5758 // is prototype for. |
| 5759 static int OwnPrototypeChainLength(JSObject* obj) { |
| 5760 int count = 1; |
| 5761 for (PrototypeIterator iter(obj->GetIsolate(), obj); |
| 5762 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { |
| 5763 count++; |
| 5764 } |
| 5765 return count; |
| 5766 } |
| 5767 |
| 5768 |
5756 // Return the names of the own named properties. | 5769 // Return the names of the own named properties. |
5757 // args[0]: object | 5770 // args[0]: object |
5758 // args[1]: PropertyAttributes as int | 5771 // args[1]: PropertyAttributes as int |
5759 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { | 5772 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { |
5760 HandleScope scope(isolate); | 5773 HandleScope scope(isolate); |
5761 DCHECK(args.length() == 2); | 5774 DCHECK(args.length() == 2); |
5762 if (!args[0]->IsJSObject()) { | 5775 if (!args[0]->IsJSObject()) { |
5763 return isolate->heap()->undefined_value(); | 5776 return isolate->heap()->undefined_value(); |
5764 } | 5777 } |
5765 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 5778 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
5766 CONVERT_SMI_ARG_CHECKED(filter_value, 1); | 5779 CONVERT_SMI_ARG_CHECKED(filter_value, 1); |
5767 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); | 5780 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); |
5768 | 5781 |
| 5782 // Skip the global proxy as it has no properties and always delegates to the |
| 5783 // real global object. |
| 5784 if (obj->IsJSGlobalProxy()) { |
| 5785 // Only collect names if access is permitted. |
| 5786 if (obj->IsAccessCheckNeeded() && |
| 5787 !isolate->MayNamedAccess( |
| 5788 obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { |
| 5789 isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS); |
| 5790 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 5791 return *isolate->factory()->NewJSArray(0); |
| 5792 } |
| 5793 PrototypeIterator iter(isolate, obj); |
| 5794 obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 5795 } |
| 5796 |
| 5797 // Find the number of objects making up this. |
| 5798 int length = OwnPrototypeChainLength(*obj); |
| 5799 |
5769 // Find the number of own properties for each of the objects. | 5800 // Find the number of own properties for each of the objects. |
| 5801 ScopedVector<int> own_property_count(length); |
5770 int total_property_count = 0; | 5802 int total_property_count = 0; |
5771 { | 5803 { |
5772 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 5804 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
5773 for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); | 5805 for (int i = 0; i < length; i++) { |
5774 iter.Advance()) { | |
5775 DCHECK(!iter.IsAtEnd()); | 5806 DCHECK(!iter.IsAtEnd()); |
5776 Handle<JSObject> jsproto = | 5807 Handle<JSObject> jsproto = |
5777 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 5808 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
5778 // Only collect names if access is permitted. | 5809 // Only collect names if access is permitted. |
5779 if (jsproto->IsAccessCheckNeeded() && | 5810 if (jsproto->IsAccessCheckNeeded() && |
5780 !isolate->MayNamedAccess(jsproto, | 5811 !isolate->MayNamedAccess(jsproto, |
5781 isolate->factory()->undefined_value(), | 5812 isolate->factory()->undefined_value(), |
5782 v8::ACCESS_KEYS)) { | 5813 v8::ACCESS_KEYS)) { |
5783 isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS); | 5814 isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS); |
5784 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 5815 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
5785 return *isolate->factory()->NewJSArray(0); | 5816 return *isolate->factory()->NewJSArray(0); |
5786 } | 5817 } |
5787 int n; | 5818 int n; |
5788 n = jsproto->NumberOfOwnProperties(filter); | 5819 n = jsproto->NumberOfOwnProperties(filter); |
| 5820 own_property_count[i] = n; |
5789 total_property_count += n; | 5821 total_property_count += n; |
| 5822 iter.Advance(); |
5790 } | 5823 } |
5791 } | 5824 } |
5792 | 5825 |
5793 // Allocate an array with storage for all the property names. | 5826 // Allocate an array with storage for all the property names. |
5794 Handle<FixedArray> names = | 5827 Handle<FixedArray> names = |
5795 isolate->factory()->NewFixedArray(total_property_count); | 5828 isolate->factory()->NewFixedArray(total_property_count); |
5796 | 5829 |
5797 // Get the property names. | 5830 // Get the property names. |
5798 int next_copy_index = 0; | 5831 int next_copy_index = 0; |
5799 int hidden_strings = 0; | 5832 int hidden_strings = 0; |
5800 { | 5833 { |
5801 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 5834 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
5802 for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); | 5835 for (int i = 0; i < length; i++) { |
5803 iter.Advance()) { | 5836 DCHECK(!iter.IsAtEnd()); |
5804 Handle<JSObject> jsproto = | 5837 Handle<JSObject> jsproto = |
5805 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 5838 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
5806 int own_property_count = | 5839 jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); |
5807 jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); | 5840 if (i > 0) { |
5808 if (!jsproto.is_identical_to(obj)) { | |
5809 // Names from hidden prototypes may already have been added | 5841 // Names from hidden prototypes may already have been added |
5810 // for inherited function template instances. Count the duplicates | 5842 // for inherited function template instances. Count the duplicates |
5811 // and stub them out; the final copy pass at the end ignores holes. | 5843 // and stub them out; the final copy pass at the end ignores holes. |
5812 for (int j = next_copy_index; j < next_copy_index + own_property_count; | 5844 for (int j = next_copy_index; |
5813 j++) { | 5845 j < next_copy_index + own_property_count[i]; j++) { |
5814 Object* name_from_hidden_proto = names->get(j); | 5846 Object* name_from_hidden_proto = names->get(j); |
5815 for (int k = 0; k < next_copy_index; k++) { | 5847 for (int k = 0; k < next_copy_index; k++) { |
5816 if (names->get(k) != isolate->heap()->hidden_string()) { | 5848 if (names->get(k) != isolate->heap()->hidden_string()) { |
5817 Object* name = names->get(k); | 5849 Object* name = names->get(k); |
5818 if (name_from_hidden_proto == name) { | 5850 if (name_from_hidden_proto == name) { |
5819 names->set(j, isolate->heap()->hidden_string()); | 5851 names->set(j, isolate->heap()->hidden_string()); |
5820 hidden_strings++; | 5852 hidden_strings++; |
5821 break; | 5853 break; |
5822 } | 5854 } |
5823 } | 5855 } |
5824 } | 5856 } |
5825 } | 5857 } |
5826 } | 5858 } |
5827 next_copy_index += own_property_count; | 5859 next_copy_index += own_property_count[i]; |
5828 | 5860 |
5829 // Hidden properties only show up if the filter does not skip strings. | 5861 // Hidden properties only show up if the filter does not skip strings. |
5830 if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) { | 5862 if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) { |
5831 hidden_strings++; | 5863 hidden_strings++; |
5832 } | 5864 } |
| 5865 iter.Advance(); |
5833 } | 5866 } |
5834 } | 5867 } |
5835 | 5868 |
5836 // Filter out name of hidden properties object and | 5869 // Filter out name of hidden properties object and |
5837 // hidden prototype duplicates. | 5870 // hidden prototype duplicates. |
5838 if (hidden_strings > 0) { | 5871 if (hidden_strings > 0) { |
5839 Handle<FixedArray> old_names = names; | 5872 Handle<FixedArray> old_names = names; |
5840 names = isolate->factory()->NewFixedArray( | 5873 names = isolate->factory()->NewFixedArray( |
5841 names->length() - hidden_strings); | 5874 names->length() - hidden_strings); |
5842 int dest_pos = 0; | 5875 int dest_pos = 0; |
(...skipping 9813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15656 } | 15689 } |
15657 return NULL; | 15690 return NULL; |
15658 } | 15691 } |
15659 | 15692 |
15660 | 15693 |
15661 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15694 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15662 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15695 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15663 } | 15696 } |
15664 | 15697 |
15665 } } // namespace v8::internal | 15698 } } // namespace v8::internal |
OLD | NEW |