OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/keys.h" | 5 #include "src/keys.h" |
6 | 6 |
7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
8 #include "src/elements.h" | 8 #include "src/elements.h" |
9 #include "src/factory.h" | 9 #include "src/factory.h" |
10 #include "src/identity-map.h" | 10 #include "src/identity-map.h" |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 MaybeHandle<FixedArray>()); | 423 MaybeHandle<FixedArray>()); |
424 return accumulator.GetKeys(keys_conversion); | 424 return accumulator.GetKeys(keys_conversion); |
425 } | 425 } |
426 | 426 |
427 namespace { | 427 namespace { |
428 | 428 |
429 enum IndexedOrNamed { kIndexed, kNamed }; | 429 enum IndexedOrNamed { kIndexed, kNamed }; |
430 | 430 |
431 // Returns |true| on success, |nothing| on exception. | 431 // Returns |true| on success, |nothing| on exception. |
432 template <class Callback, IndexedOrNamed type> | 432 template <class Callback, IndexedOrNamed type> |
| 433 Maybe<bool> CollectInterceptorKeysInternal(Handle<JSReceiver> receiver, |
| 434 Handle<JSObject> object, |
| 435 Handle<InterceptorInfo> interceptor, |
| 436 KeyAccumulator* accumulator) { |
| 437 Isolate* isolate = accumulator->isolate(); |
| 438 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, |
| 439 *object, Object::DONT_THROW); |
| 440 Handle<JSObject> result; |
| 441 if (!interceptor->enumerator()->IsUndefined(isolate)) { |
| 442 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); |
| 443 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" |
| 444 : "interceptor-named-enum"; |
| 445 LOG(isolate, ApiObjectAccess(log_tag, *object)); |
| 446 result = args.Call(enum_fun); |
| 447 } |
| 448 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
| 449 if (result.is_null()) return Just(true); |
| 450 accumulator->AddKeys( |
| 451 result, type == kIndexed ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); |
| 452 return Just(true); |
| 453 } |
| 454 |
| 455 template <class Callback, IndexedOrNamed type> |
433 Maybe<bool> CollectInterceptorKeys(Handle<JSReceiver> receiver, | 456 Maybe<bool> CollectInterceptorKeys(Handle<JSReceiver> receiver, |
434 Handle<JSObject> object, | 457 Handle<JSObject> object, |
435 KeyAccumulator* accumulator) { | 458 KeyAccumulator* accumulator) { |
436 Isolate* isolate = accumulator->isolate(); | 459 Isolate* isolate = accumulator->isolate(); |
437 if (type == kIndexed) { | 460 if (type == kIndexed) { |
438 if (!object->HasIndexedInterceptor()) return Just(true); | 461 if (!object->HasIndexedInterceptor()) return Just(true); |
439 } else { | 462 } else { |
440 if (!object->HasNamedInterceptor()) return Just(true); | 463 if (!object->HasNamedInterceptor()) return Just(true); |
441 } | 464 } |
442 Handle<InterceptorInfo> interceptor(type == kIndexed | 465 Handle<InterceptorInfo> interceptor(type == kIndexed |
443 ? object->GetIndexedInterceptor() | 466 ? object->GetIndexedInterceptor() |
444 : object->GetNamedInterceptor(), | 467 : object->GetNamedInterceptor(), |
445 isolate); | 468 isolate); |
446 if ((accumulator->filter() & ONLY_ALL_CAN_READ) && | 469 if ((accumulator->filter() & ONLY_ALL_CAN_READ) && |
447 !interceptor->all_can_read()) { | 470 !interceptor->all_can_read()) { |
448 return Just(true); | 471 return Just(true); |
449 } | 472 } |
450 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, | 473 return CollectInterceptorKeysInternal<Callback, type>( |
451 *object, Object::DONT_THROW); | 474 receiver, object, interceptor, accumulator); |
452 Handle<JSObject> result; | |
453 if (!interceptor->enumerator()->IsUndefined(isolate)) { | |
454 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); | |
455 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" | |
456 : "interceptor-named-enum"; | |
457 LOG(isolate, ApiObjectAccess(log_tag, *object)); | |
458 result = args.Call(enum_fun); | |
459 } | |
460 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); | |
461 if (result.is_null()) return Just(true); | |
462 accumulator->AddKeys( | |
463 result, type == kIndexed ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); | |
464 return Just(true); | |
465 } | 475 } |
466 | 476 |
467 } // namespace | 477 } // namespace |
468 | 478 |
469 Maybe<bool> KeyAccumulator::CollectOwnElementIndices( | 479 Maybe<bool> KeyAccumulator::CollectOwnElementIndices( |
470 Handle<JSReceiver> receiver, Handle<JSObject> object) { | 480 Handle<JSReceiver> receiver, Handle<JSObject> object) { |
471 if (filter_ & SKIP_STRINGS || skip_indices_) return Just(true); | 481 if (filter_ & SKIP_STRINGS || skip_indices_) return Just(true); |
472 | 482 |
473 ElementsAccessor* accessor = object->GetElementsAccessor(); | 483 ElementsAccessor* accessor = object->GetElementsAccessor(); |
474 accessor->CollectElementIndices(object, this); | 484 accessor->CollectElementIndices(object, this); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 } else { | 542 } else { |
533 NameDictionary::CollectKeysTo( | 543 NameDictionary::CollectKeysTo( |
534 handle(object->property_dictionary(), isolate_), this, filter_); | 544 handle(object->property_dictionary(), isolate_), this, filter_); |
535 } | 545 } |
536 } | 546 } |
537 // Add the property keys from the interceptor. | 547 // Add the property keys from the interceptor. |
538 return CollectInterceptorKeys<v8::GenericNamedPropertyEnumeratorCallback, | 548 return CollectInterceptorKeys<v8::GenericNamedPropertyEnumeratorCallback, |
539 kNamed>(receiver, object, this); | 549 kNamed>(receiver, object, this); |
540 } | 550 } |
541 | 551 |
| 552 Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys( |
| 553 Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver, |
| 554 Handle<JSObject> object) { |
| 555 MAYBE_RETURN( |
| 556 (CollectInterceptorKeysInternal<v8::IndexedPropertyEnumeratorCallback, |
| 557 kIndexed>( |
| 558 receiver, object, |
| 559 handle( |
| 560 InterceptorInfo::cast(access_check_info->indexed_interceptor()), |
| 561 isolate_), |
| 562 this)), |
| 563 Nothing<bool>()); |
| 564 MAYBE_RETURN( |
| 565 (CollectInterceptorKeysInternal< |
| 566 v8::GenericNamedPropertyEnumeratorCallback, kNamed>( |
| 567 receiver, object, |
| 568 handle(InterceptorInfo::cast(access_check_info->named_interceptor()), |
| 569 isolate_), |
| 570 this)), |
| 571 Nothing<bool>()); |
| 572 return Just(true); |
| 573 } |
| 574 |
542 // Returns |true| on success, |false| if prototype walking should be stopped, | 575 // Returns |true| on success, |false| if prototype walking should be stopped, |
543 // |nothing| if an exception was thrown. | 576 // |nothing| if an exception was thrown. |
544 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, | 577 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, |
545 Handle<JSObject> object) { | 578 Handle<JSObject> object) { |
546 // Check access rights if required. | 579 // Check access rights if required. |
547 if (object->IsAccessCheckNeeded() && | 580 if (object->IsAccessCheckNeeded() && |
548 !isolate_->MayAccess(handle(isolate_->context()), object)) { | 581 !isolate_->MayAccess(handle(isolate_->context()), object)) { |
549 // The cross-origin spec says that [[Enumerate]] shall return an empty | 582 // The cross-origin spec says that [[Enumerate]] shall return an empty |
550 // iterator when it doesn't have access... | 583 // iterator when it doesn't have access... |
551 if (mode_ == KeyCollectionMode::kIncludePrototypes) { | 584 if (mode_ == KeyCollectionMode::kIncludePrototypes) { |
552 return Just(false); | 585 return Just(false); |
553 } | 586 } |
554 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 587 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
555 DCHECK(KeyCollectionMode::kOwnOnly == mode_); | 588 DCHECK(KeyCollectionMode::kOwnOnly == mode_); |
| 589 Handle<AccessCheckInfo> access_check_info; |
| 590 { |
| 591 DisallowHeapAllocation no_gc; |
| 592 AccessCheckInfo* maybe_info = AccessCheckInfo::Get(isolate_, object); |
| 593 if (maybe_info) access_check_info = handle(maybe_info, isolate_); |
| 594 } |
| 595 // We always have both kinds of interceptors or none. |
| 596 if (!access_check_info.is_null() && |
| 597 access_check_info->named_interceptor()) { |
| 598 MAYBE_RETURN(CollectAccessCheckInterceptorKeys(access_check_info, |
| 599 receiver, object), |
| 600 Nothing<bool>()); |
| 601 return Just(false); |
| 602 } |
556 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); | 603 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); |
557 } | 604 } |
558 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); | 605 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); |
559 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); | 606 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); |
560 return Just(true); | 607 return Just(true); |
561 } | 608 } |
562 | 609 |
563 // static | 610 // static |
564 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys( | 611 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys( |
565 Isolate* isolate, Handle<JSObject> object) { | 612 Isolate* isolate, Handle<JSObject> object) { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); | 788 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); |
742 bool prev_filter_proxy_keys_ = filter_proxy_keys_; | 789 bool prev_filter_proxy_keys_ = filter_proxy_keys_; |
743 filter_proxy_keys_ = false; | 790 filter_proxy_keys_ = false; |
744 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); | 791 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
745 filter_proxy_keys_ = prev_filter_proxy_keys_; | 792 filter_proxy_keys_ = prev_filter_proxy_keys_; |
746 return result; | 793 return result; |
747 } | 794 } |
748 | 795 |
749 } // namespace internal | 796 } // namespace internal |
750 } // namespace v8 | 797 } // namespace v8 |
OLD | NEW |