| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 4c8723cdd44f3b07b3e91935e232eb7fc3e36f57..23360fefc41a2123e5ed1dde78529eafdf45b5ff 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -5753,6 +5753,19 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
|
| }
|
|
|
|
|
| +// Find the length of the prototype chain that is to be handled as one. If a
|
| +// prototype object is hidden it is to be viewed as part of the the object it
|
| +// is prototype for.
|
| +static int OwnPrototypeChainLength(JSObject* obj) {
|
| + int count = 1;
|
| + for (PrototypeIterator iter(obj->GetIsolate(), obj);
|
| + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
| + count++;
|
| + }
|
| + return count;
|
| +}
|
| +
|
| +
|
| // Return the names of the own named properties.
|
| // args[0]: object
|
| // args[1]: PropertyAttributes as int
|
| @@ -5766,12 +5779,30 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| CONVERT_SMI_ARG_CHECKED(filter_value, 1);
|
| PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
|
|
|
| + // Skip the global proxy as it has no properties and always delegates to the
|
| + // real global object.
|
| + if (obj->IsJSGlobalProxy()) {
|
| + // Only collect names if access is permitted.
|
| + if (obj->IsAccessCheckNeeded() &&
|
| + !isolate->MayNamedAccess(
|
| + obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
|
| + isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
|
| + RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| + return *isolate->factory()->NewJSArray(0);
|
| + }
|
| + PrototypeIterator iter(isolate, obj);
|
| + obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| + }
|
| +
|
| + // Find the number of objects making up this.
|
| + int length = OwnPrototypeChainLength(*obj);
|
| +
|
| // Find the number of own properties for each of the objects.
|
| + ScopedVector<int> own_property_count(length);
|
| int total_property_count = 0;
|
| {
|
| PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
| - for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN);
|
| - iter.Advance()) {
|
| + for (int i = 0; i < length; i++) {
|
| DCHECK(!iter.IsAtEnd());
|
| Handle<JSObject> jsproto =
|
| Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| @@ -5786,7 +5817,9 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| }
|
| int n;
|
| n = jsproto->NumberOfOwnProperties(filter);
|
| + own_property_count[i] = n;
|
| total_property_count += n;
|
| + iter.Advance();
|
| }
|
| }
|
|
|
| @@ -5799,18 +5832,17 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| int hidden_strings = 0;
|
| {
|
| PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
| - for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN);
|
| - iter.Advance()) {
|
| + for (int i = 0; i < length; i++) {
|
| + DCHECK(!iter.IsAtEnd());
|
| Handle<JSObject> jsproto =
|
| Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| - int own_property_count =
|
| - jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
| - if (!jsproto.is_identical_to(obj)) {
|
| + jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
| + if (i > 0) {
|
| // Names from hidden prototypes may already have been added
|
| // for inherited function template instances. Count the duplicates
|
| // and stub them out; the final copy pass at the end ignores holes.
|
| - for (int j = next_copy_index; j < next_copy_index + own_property_count;
|
| - j++) {
|
| + for (int j = next_copy_index;
|
| + j < next_copy_index + own_property_count[i]; j++) {
|
| Object* name_from_hidden_proto = names->get(j);
|
| for (int k = 0; k < next_copy_index; k++) {
|
| if (names->get(k) != isolate->heap()->hidden_string()) {
|
| @@ -5824,12 +5856,13 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| }
|
| }
|
| }
|
| - next_copy_index += own_property_count;
|
| + next_copy_index += own_property_count[i];
|
|
|
| // Hidden properties only show up if the filter does not skip strings.
|
| if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
|
| hidden_strings++;
|
| }
|
| + iter.Advance();
|
| }
|
| }
|
|
|
|
|