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" |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 isolate, content, | 803 isolate, content, |
804 JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); | 804 JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); |
805 | 805 |
806 // Test again, since cache may have been built by preceding call. | 806 // Test again, since cache may have been built by preceding call. |
807 if (object->IsSimpleEnum()) return object->map(); | 807 if (object->IsSimpleEnum()) return object->map(); |
808 | 808 |
809 return *content; | 809 return *content; |
810 } | 810 } |
811 | 811 |
812 | 812 |
813 // Find the length of the prototype chain that is to be handled as one. If a | |
814 // prototype object is hidden it is to be viewed as part of the the object it | |
815 // is prototype for. | |
816 static int OwnPrototypeChainLength(JSObject* obj) { | |
817 int count = 1; | |
818 for (PrototypeIterator iter(obj->GetIsolate(), obj); | |
819 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { | |
820 count++; | |
821 } | |
822 return count; | |
823 } | |
824 | |
825 | |
826 // Return the names of the own named properties. | 813 // Return the names of the own named properties. |
827 // args[0]: object | 814 // args[0]: object |
828 // args[1]: PropertyAttributes as int | 815 // args[1]: PropertyAttributes as int |
829 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { | 816 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { |
830 HandleScope scope(isolate); | 817 HandleScope scope(isolate); |
831 DCHECK(args.length() == 2); | 818 DCHECK(args.length() == 2); |
832 if (!args[0]->IsJSObject()) { | 819 if (!args[0]->IsJSObject()) { |
833 return isolate->heap()->undefined_value(); | 820 return isolate->heap()->undefined_value(); |
834 } | 821 } |
835 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 822 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
836 CONVERT_SMI_ARG_CHECKED(filter_value, 1); | 823 CONVERT_SMI_ARG_CHECKED(filter_value, 1); |
837 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); | 824 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); |
838 | 825 |
839 // Skip the global proxy as it has no properties and always delegates to the | |
840 // real global object. | |
841 if (obj->IsJSGlobalProxy()) { | |
842 // Only collect names if access is permitted. | |
843 if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) { | |
844 isolate->ReportFailedAccessCheck(obj); | |
845 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
846 return *isolate->factory()->NewJSArray(0); | |
847 } | |
848 PrototypeIterator iter(isolate, obj); | |
849 obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
850 } | |
851 | |
852 // Find the number of objects making up this. | |
853 int length = OwnPrototypeChainLength(*obj); | |
854 | |
855 // Find the number of own properties for each of the objects. | 826 // Find the number of own properties for each of the objects. |
856 ScopedVector<int> own_property_count(length); | |
857 int total_property_count = 0; | 827 int total_property_count = 0; |
858 { | 828 for (PrototypeIterator iter(isolate, object, |
859 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 829 PrototypeIterator::START_AT_RECEIVER); |
860 for (int i = 0; i < length; i++) { | 830 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { |
861 DCHECK(!iter.IsAtEnd()); | 831 Handle<JSObject> jsproto = |
862 Handle<JSObject> jsproto = | 832 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
863 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 833 total_property_count += jsproto->NumberOfOwnProperties(filter); |
864 // Only collect names if access is permitted. | |
865 if (jsproto->IsAccessCheckNeeded() && !isolate->MayAccess(jsproto)) { | |
866 isolate->ReportFailedAccessCheck(jsproto); | |
867 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
868 return *isolate->factory()->NewJSArray(0); | |
869 } | |
870 int n; | |
871 n = jsproto->NumberOfOwnProperties(filter); | |
872 own_property_count[i] = n; | |
873 total_property_count += n; | |
874 iter.Advance(); | |
875 } | |
876 } | 834 } |
877 | 835 |
878 // Allocate an array with storage for all the property names. | 836 // Allocate an array with storage for all the property names. |
879 Handle<FixedArray> names = | 837 Handle<FixedArray> names = |
880 isolate->factory()->NewFixedArray(total_property_count); | 838 isolate->factory()->NewFixedArray(total_property_count); |
881 | 839 |
882 // Get the property names. | 840 // Get the property names. |
883 int next_copy_index = 0; | 841 int next_copy_index = 0; |
884 int hidden_strings = 0; | 842 int hidden_strings = 0; |
885 { | 843 Handle<Object> hidden_string = isolate->factory()->hidden_string(); |
886 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 844 for (PrototypeIterator iter(isolate, object, |
887 for (int i = 0; i < length; i++) { | 845 PrototypeIterator::START_AT_RECEIVER); |
888 DCHECK(!iter.IsAtEnd()); | 846 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { |
889 Handle<JSObject> jsproto = | 847 Handle<JSObject> jsproto = |
890 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 848 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
891 jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); | 849 int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); |
892 // Names from hidden prototypes may already have been added | 850 // Names from hidden prototypes may already have been added |
893 // for inherited function template instances. Count the duplicates | 851 // for inherited function template instances. Count the duplicates |
894 // and stub them out; the final copy pass at the end ignores holes. | 852 // and stub them out; the final copy pass at the end ignores holes. |
895 for (int j = next_copy_index; j < next_copy_index + own_property_count[i]; | 853 for (int j = next_copy_index; j < next_copy_index + own; j++) { |
896 j++) { | 854 Object* name_from_hidden_proto = names->get(j); |
897 Object* name_from_hidden_proto = names->get(j); | 855 if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { |
898 if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { | 856 hidden_strings++; |
899 hidden_strings++; | 857 } else { |
900 } else { | 858 for (int k = 0; k < next_copy_index; k++) { |
901 for (int k = 0; k < next_copy_index; k++) { | 859 Object* name = names->get(k); |
902 Object* name = names->get(k); | 860 if (name_from_hidden_proto == name) { |
903 if (name_from_hidden_proto == name) { | 861 names->set(j, *hidden_string); |
904 names->set(j, isolate->heap()->hidden_string()); | 862 hidden_strings++; |
905 hidden_strings++; | 863 break; |
906 break; | |
907 } | |
908 } | 864 } |
909 } | 865 } |
910 } | 866 } |
911 next_copy_index += own_property_count[i]; | 867 } |
| 868 next_copy_index += own; |
| 869 } |
912 | 870 |
913 iter.Advance(); | 871 CHECK_EQ(total_property_count, next_copy_index); |
| 872 |
| 873 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
| 874 for (int i = 0; i < total_property_count; i++) { |
| 875 Handle<Name> name(Name::cast(names->get(i))); |
| 876 if (name.is_identical_to(hidden_string)) continue; |
| 877 LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); |
| 878 if (!JSObject::AllCanRead(&it)) { |
| 879 names->set(i, *hidden_string); |
| 880 hidden_strings++; |
| 881 } |
914 } | 882 } |
915 } | 883 } |
916 | 884 |
917 // Filter out name of hidden properties object and | 885 // Filter out name of hidden properties object and |
918 // hidden prototype duplicates. | 886 // hidden prototype duplicates. |
919 if (hidden_strings > 0) { | 887 if (hidden_strings > 0) { |
920 Handle<FixedArray> old_names = names; | 888 if (hidden_strings == total_property_count) { |
921 names = isolate->factory()->NewFixedArray(names->length() - hidden_strings); | 889 names = isolate->factory()->empty_fixed_array(); |
922 int dest_pos = 0; | 890 } else { |
923 for (int i = 0; i < total_property_count; i++) { | 891 int i; |
924 Object* name = old_names->get(i); | 892 for (i = 0; i < total_property_count; i++) { |
925 if (isolate->IsInternallyUsedPropertyName(name)) { | 893 Object* name = names->get(i); |
926 hidden_strings--; | 894 if (name == *hidden_string) break; |
927 continue; | |
928 } | 895 } |
929 names->set(dest_pos++, name); | 896 int dest_pos = i; |
| 897 for (; i < total_property_count; i++) { |
| 898 Object* name = names->get(i); |
| 899 if (name == *hidden_string) continue; |
| 900 names->set(dest_pos++, name); |
| 901 } |
| 902 |
| 903 isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
| 904 *names, hidden_strings); |
930 } | 905 } |
931 DCHECK_EQ(0, hidden_strings); | |
932 } | 906 } |
933 | 907 |
934 return *isolate->factory()->NewJSArrayWithElements(names); | 908 return *isolate->factory()->NewJSArrayWithElements(names); |
935 } | 909 } |
936 | 910 |
937 | 911 |
938 // Return the names of the own indexed properties. | 912 // Return the names of the own indexed properties. |
939 // args[0]: object | 913 // args[0]: object |
940 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) { | 914 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) { |
941 HandleScope scope(isolate); | 915 HandleScope scope(isolate); |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1470 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1444 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
1471 | 1445 |
1472 RETURN_FAILURE_ON_EXCEPTION( | 1446 RETURN_FAILURE_ON_EXCEPTION( |
1473 isolate, | 1447 isolate, |
1474 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), | 1448 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), |
1475 setter, attrs)); | 1449 setter, attrs)); |
1476 return isolate->heap()->undefined_value(); | 1450 return isolate->heap()->undefined_value(); |
1477 } | 1451 } |
1478 } // namespace internal | 1452 } // namespace internal |
1479 } // namespace v8 | 1453 } // namespace v8 |
OLD | NEW |