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