| 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 |