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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "accessors.h" | 7 #include "accessors.h" |
8 #include "allocation-site-scopes.h" | 8 #include "allocation-site-scopes.h" |
9 #include "api.h" | 9 #include "api.h" |
10 #include "arguments.h" | 10 #include "arguments.h" |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 | 533 |
534 Handle<Object> argv[] = { value }; | 534 Handle<Object> argv[] = { value }; |
535 RETURN_ON_EXCEPTION( | 535 RETURN_ON_EXCEPTION( |
536 isolate, | 536 isolate, |
537 Execution::Call(isolate, setter, receiver, ARRAY_SIZE(argv), argv), | 537 Execution::Call(isolate, setter, receiver, ARRAY_SIZE(argv), argv), |
538 Object); | 538 Object); |
539 return value; | 539 return value; |
540 } | 540 } |
541 | 541 |
542 | 542 |
543 // Only deal with CALLBACKS and INTERCEPTOR | 543 static bool FindAllCanReadHolder(LookupResult* result, |
| 544 Handle<Name> name, |
| 545 bool check_prototype) { |
| 546 if (result->IsInterceptor()) { |
| 547 result->holder()->LookupOwnRealNamedProperty(name, result); |
| 548 } |
| 549 |
| 550 while (result->IsProperty()) { |
| 551 if (result->type() == CALLBACKS) { |
| 552 Object* callback_obj = result->GetCallbackObject(); |
| 553 if (callback_obj->IsAccessorInfo()) { |
| 554 if (AccessorInfo::cast(callback_obj)->all_can_read()) return true; |
| 555 } else if (callback_obj->IsAccessorPair()) { |
| 556 if (AccessorPair::cast(callback_obj)->all_can_read()) return true; |
| 557 } |
| 558 } |
| 559 if (!check_prototype) break; |
| 560 result->holder()->LookupRealNamedPropertyInPrototypes(name, result); |
| 561 } |
| 562 return false; |
| 563 } |
| 564 |
| 565 |
544 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( | 566 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
545 Handle<JSObject> object, | 567 Handle<JSObject> object, |
546 Handle<Object> receiver, | 568 Handle<Object> receiver, |
547 LookupResult* result, | 569 LookupResult* result, |
548 Handle<Name> name, | 570 Handle<Name> name, |
549 PropertyAttributes* attributes) { | 571 PropertyAttributes* attributes) { |
550 Isolate* isolate = name->GetIsolate(); | 572 if (FindAllCanReadHolder(result, name, true)) { |
551 if (result->IsProperty()) { | 573 *attributes = result->GetAttributes(); |
552 switch (result->type()) { | 574 Handle<JSObject> holder(result->holder()); |
553 case CALLBACKS: { | 575 Handle<Object> callbacks(result->GetCallbackObject(), result->isolate()); |
554 // Only allow API accessors. | 576 return GetPropertyWithCallback(receiver, name, holder, callbacks); |
555 Handle<Object> callback_obj(result->GetCallbackObject(), isolate); | |
556 if (callback_obj->IsAccessorInfo()) { | |
557 if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break; | |
558 *attributes = result->GetAttributes(); | |
559 // Fall through to GetPropertyWithCallback. | |
560 } else if (callback_obj->IsAccessorPair()) { | |
561 if (!AccessorPair::cast(*callback_obj)->all_can_read()) break; | |
562 // Fall through to GetPropertyWithCallback. | |
563 } else { | |
564 break; | |
565 } | |
566 Handle<JSObject> holder(result->holder(), isolate); | |
567 return GetPropertyWithCallback(receiver, name, holder, callback_obj); | |
568 } | |
569 case NORMAL: | |
570 case FIELD: | |
571 case CONSTANT: { | |
572 // Search ALL_CAN_READ accessors in prototype chain. | |
573 LookupResult r(isolate); | |
574 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | |
575 if (r.IsProperty()) { | |
576 return GetPropertyWithFailedAccessCheck( | |
577 object, receiver, &r, name, attributes); | |
578 } | |
579 break; | |
580 } | |
581 case INTERCEPTOR: { | |
582 // If the object has an interceptor, try real named properties. | |
583 // No access check in GetPropertyAttributeWithInterceptor. | |
584 LookupResult r(isolate); | |
585 result->holder()->LookupRealNamedProperty(name, &r); | |
586 if (r.IsProperty()) { | |
587 return GetPropertyWithFailedAccessCheck( | |
588 object, receiver, &r, name, attributes); | |
589 } | |
590 break; | |
591 } | |
592 default: | |
593 UNREACHABLE(); | |
594 } | |
595 } | 577 } |
596 | |
597 // No accessible property found. | |
598 *attributes = ABSENT; | 578 *attributes = ABSENT; |
| 579 Isolate* isolate = result->isolate(); |
599 isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET); | 580 isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET); |
600 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 581 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
601 return isolate->factory()->undefined_value(); | 582 return isolate->factory()->undefined_value(); |
602 } | 583 } |
603 | 584 |
604 | 585 |
605 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 586 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
606 Handle<JSObject> object, | 587 Handle<JSObject> object, |
607 LookupResult* result, | 588 LookupResult* result, |
608 Handle<Name> name, | 589 Handle<Name> name, |
609 bool continue_search) { | 590 bool check_prototype) { |
610 if (result->IsProperty()) { | 591 if (FindAllCanReadHolder(result, name, check_prototype)) { |
611 switch (result->type()) { | 592 return result->GetAttributes(); |
612 case CALLBACKS: { | |
613 // Only allow API accessors. | |
614 Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate()); | |
615 if (obj->IsAccessorInfo()) { | |
616 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj); | |
617 if (info->all_can_read()) { | |
618 return result->GetAttributes(); | |
619 } | |
620 } else if (obj->IsAccessorPair()) { | |
621 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj); | |
622 if (pair->all_can_read()) { | |
623 return result->GetAttributes(); | |
624 } | |
625 } | |
626 break; | |
627 } | |
628 | |
629 case NORMAL: | |
630 case FIELD: | |
631 case CONSTANT: { | |
632 if (!continue_search) break; | |
633 // Search ALL_CAN_READ accessors in prototype chain. | |
634 LookupResult r(object->GetIsolate()); | |
635 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | |
636 if (r.IsProperty()) { | |
637 return GetPropertyAttributeWithFailedAccessCheck( | |
638 object, &r, name, continue_search); | |
639 } | |
640 break; | |
641 } | |
642 | |
643 case INTERCEPTOR: { | |
644 // If the object has an interceptor, try real named properties. | |
645 // No access check in GetPropertyAttributeWithInterceptor. | |
646 LookupResult r(object->GetIsolate()); | |
647 if (continue_search) { | |
648 result->holder()->LookupRealNamedProperty(name, &r); | |
649 } else { | |
650 result->holder()->LookupOwnRealNamedProperty(name, &r); | |
651 } | |
652 if (!r.IsFound()) break; | |
653 return GetPropertyAttributeWithFailedAccessCheck( | |
654 object, &r, name, continue_search); | |
655 } | |
656 | |
657 case HANDLER: | |
658 case NONEXISTENT: | |
659 UNREACHABLE(); | |
660 } | |
661 } | 593 } |
662 | 594 result->isolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
663 object->GetIsolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | |
664 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 595 // TODO(yangguo): Issue 3269, check for scheduled exception missing? |
665 return ABSENT; | 596 return ABSENT; |
666 } | 597 } |
667 | 598 |
668 | 599 |
| 600 static bool FindAllCanWriteHolder(LookupResult* result, |
| 601 Handle<Name> name, |
| 602 bool check_prototype) { |
| 603 if (result->IsInterceptor()) { |
| 604 result->holder()->LookupOwnRealNamedProperty(name, result); |
| 605 } |
| 606 |
| 607 while (result->IsProperty()) { |
| 608 if (result->type() == CALLBACKS) { |
| 609 Object* callback_obj = result->GetCallbackObject(); |
| 610 if (callback_obj->IsAccessorInfo()) { |
| 611 if (AccessorInfo::cast(callback_obj)->all_can_write()) return true; |
| 612 } else if (callback_obj->IsAccessorPair()) { |
| 613 if (AccessorPair::cast(callback_obj)->all_can_write()) return true; |
| 614 } |
| 615 } |
| 616 if (!check_prototype) break; |
| 617 result->holder()->LookupRealNamedPropertyInPrototypes(name, result); |
| 618 } |
| 619 return false; |
| 620 } |
| 621 |
| 622 |
| 623 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
| 624 Handle<JSObject> object, |
| 625 LookupResult* result, |
| 626 Handle<Name> name, |
| 627 Handle<Object> value, |
| 628 bool check_prototype, |
| 629 StrictMode strict_mode) { |
| 630 if (check_prototype && !result->IsProperty()) { |
| 631 object->LookupRealNamedPropertyInPrototypes(name, result); |
| 632 } |
| 633 |
| 634 if (FindAllCanWriteHolder(result, name, check_prototype)) { |
| 635 Handle<JSObject> holder(result->holder()); |
| 636 Handle<Object> callbacks(result->GetCallbackObject(), result->isolate()); |
| 637 return SetPropertyWithCallback( |
| 638 object, name, value, holder, callbacks, strict_mode); |
| 639 } |
| 640 |
| 641 Isolate* isolate = object->GetIsolate(); |
| 642 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |
| 643 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 644 return value; |
| 645 } |
| 646 |
| 647 |
669 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { | 648 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { |
670 ASSERT(!HasFastProperties()); | 649 ASSERT(!HasFastProperties()); |
671 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 650 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
672 if (IsGlobalObject()) { | 651 if (IsGlobalObject()) { |
673 value = PropertyCell::cast(value)->value(); | 652 value = PropertyCell::cast(value)->value(); |
674 } | 653 } |
675 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 654 ASSERT(!value->IsPropertyCell() && !value->IsCell()); |
676 return value; | 655 return value; |
677 } | 656 } |
678 | 657 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 // Traverse the prototype chain from the current object (this) to | 806 // Traverse the prototype chain from the current object (this) to |
828 // the holder and check for access rights. This avoids traversing the | 807 // the holder and check for access rights. This avoids traversing the |
829 // objects more than once in case of interceptors, because the | 808 // objects more than once in case of interceptors, because the |
830 // holder will always be the interceptor holder and the search may | 809 // holder will always be the interceptor holder and the search may |
831 // only continue with a current object just after the interceptor | 810 // only continue with a current object just after the interceptor |
832 // holder in the prototype chain. | 811 // holder in the prototype chain. |
833 // Proxy handlers do not use the proxy's prototype, so we can skip this. | 812 // Proxy handlers do not use the proxy's prototype, so we can skip this. |
834 if (!result->IsHandler()) { | 813 if (!result->IsHandler()) { |
835 ASSERT(*object != object->GetPrototype(isolate)); | 814 ASSERT(*object != object->GetPrototype(isolate)); |
836 Handle<Object> last = result->IsProperty() | 815 Handle<Object> last = result->IsProperty() |
837 ? Handle<Object>(result->holder(), isolate) | 816 ? handle(result->holder()->GetPrototype(), isolate) |
838 : Handle<Object>::cast(factory->null_value()); | 817 : Handle<Object>::cast(factory->null_value()); |
839 for (Handle<Object> current = object; | 818 for (Handle<Object> current = object; |
840 true; | 819 !current.is_identical_to(last); |
841 current = Handle<Object>(current->GetPrototype(isolate), isolate)) { | 820 current = Object::GetPrototype(isolate, current)) { |
842 if (current->IsAccessCheckNeeded()) { | 821 if (current->IsAccessCheckNeeded()) { |
843 // Check if we're allowed to read from the current object. Note | 822 // Check if we're allowed to read from the current object. Note |
844 // that even though we may not actually end up loading the named | 823 // that even though we may not actually end up loading the named |
845 // property from the current object, we still check that we have | 824 // property from the current object, we still check that we have |
846 // access to it. | 825 // access to it. |
847 Handle<JSObject> checked = Handle<JSObject>::cast(current); | 826 Handle<JSObject> checked = Handle<JSObject>::cast(current); |
848 if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 827 if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
849 return JSObject::GetPropertyWithFailedAccessCheck( | 828 return JSObject::GetPropertyWithFailedAccessCheck( |
850 checked, receiver, result, name, attributes); | 829 checked, receiver, result, name, attributes); |
851 } | 830 } |
852 } | 831 } |
853 // Stop traversing the chain once we reach the last object in the | |
854 // chain; either the holder of the result or null in case of an | |
855 // absent property. | |
856 if (current.is_identical_to(last)) break; | |
857 } | 832 } |
858 } | 833 } |
859 | 834 |
860 if (!result->IsProperty()) { | 835 if (!result->IsProperty()) { |
861 *attributes = ABSENT; | 836 *attributes = ABSENT; |
862 return factory->undefined_value(); | 837 return factory->undefined_value(); |
863 } | 838 } |
864 *attributes = result->GetAttributes(); | 839 *attributes = result->GetAttributes(); |
865 | 840 |
866 Handle<Object> value; | 841 Handle<Object> value; |
(...skipping 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3596 return result->HandlerResult(JSProxy::cast(pt)); | 3571 return result->HandlerResult(JSProxy::cast(pt)); |
3597 } | 3572 } |
3598 JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result); | 3573 JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result); |
3599 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3574 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
3600 if (result->IsFound()) return; | 3575 if (result->IsFound()) return; |
3601 } | 3576 } |
3602 result->NotFound(); | 3577 result->NotFound(); |
3603 } | 3578 } |
3604 | 3579 |
3605 | 3580 |
3606 // We only need to deal with CALLBACKS and INTERCEPTORS | |
3607 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( | |
3608 Handle<JSObject> object, | |
3609 LookupResult* result, | |
3610 Handle<Name> name, | |
3611 Handle<Object> value, | |
3612 bool check_prototype, | |
3613 StrictMode strict_mode) { | |
3614 if (check_prototype && !result->IsProperty()) { | |
3615 object->LookupRealNamedPropertyInPrototypes(name, result); | |
3616 } | |
3617 | |
3618 if (result->IsProperty()) { | |
3619 if (!result->IsReadOnly()) { | |
3620 switch (result->type()) { | |
3621 case CALLBACKS: { | |
3622 Object* obj = result->GetCallbackObject(); | |
3623 if (obj->IsAccessorInfo()) { | |
3624 Handle<AccessorInfo> info(AccessorInfo::cast(obj)); | |
3625 if (info->all_can_write()) { | |
3626 return SetPropertyWithCallback(object, name, value, | |
3627 handle(result->holder()), | |
3628 info, strict_mode); | |
3629 } | |
3630 } else if (obj->IsAccessorPair()) { | |
3631 Handle<AccessorPair> pair(AccessorPair::cast(obj)); | |
3632 if (pair->all_can_read()) { | |
3633 return SetPropertyWithCallback(object, name, value, | |
3634 handle(result->holder()), | |
3635 pair, strict_mode); | |
3636 } | |
3637 } | |
3638 break; | |
3639 } | |
3640 case INTERCEPTOR: { | |
3641 // Try lookup real named properties. Note that only property can be | |
3642 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | |
3643 LookupResult r(object->GetIsolate()); | |
3644 object->LookupRealNamedProperty(name, &r); | |
3645 if (r.IsProperty()) { | |
3646 return SetPropertyWithFailedAccessCheck(object, | |
3647 &r, | |
3648 name, | |
3649 value, | |
3650 check_prototype, | |
3651 strict_mode); | |
3652 } | |
3653 break; | |
3654 } | |
3655 default: { | |
3656 break; | |
3657 } | |
3658 } | |
3659 } | |
3660 } | |
3661 | |
3662 Isolate* isolate = object->GetIsolate(); | |
3663 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); | |
3664 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
3665 return value; | |
3666 } | |
3667 | |
3668 | |
3669 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 3581 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
3670 LookupResult* result, | 3582 LookupResult* result, |
3671 Handle<Name> key, | 3583 Handle<Name> key, |
3672 Handle<Object> value, | 3584 Handle<Object> value, |
3673 PropertyAttributes attributes, | 3585 PropertyAttributes attributes, |
3674 StrictMode strict_mode, | 3586 StrictMode strict_mode, |
3675 StoreFromKeyed store_mode) { | 3587 StoreFromKeyed store_mode) { |
3676 if (result->IsHandler()) { | 3588 if (result->IsHandler()) { |
3677 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), | 3589 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), |
3678 object, key, value, attributes, strict_mode); | 3590 object, key, value, attributes, strict_mode); |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4498 } | 4410 } |
4499 | 4411 |
4500 return value; | 4412 return value; |
4501 } | 4413 } |
4502 | 4414 |
4503 | 4415 |
4504 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4416 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
4505 Handle<JSObject> object, | 4417 Handle<JSObject> object, |
4506 Handle<JSObject> receiver, | 4418 Handle<JSObject> receiver, |
4507 Handle<Name> name, | 4419 Handle<Name> name, |
4508 bool continue_search) { | 4420 bool check_prototype) { |
4509 // Check own property, ignore interceptor. | 4421 // Check own property, ignore interceptor. |
4510 Isolate* isolate = object->GetIsolate(); | 4422 Isolate* isolate = object->GetIsolate(); |
4511 LookupResult result(isolate); | 4423 LookupResult result(isolate); |
4512 object->LookupOwnRealNamedProperty(name, &result); | 4424 object->LookupOwnRealNamedProperty(name, &result); |
4513 if (result.IsFound()) return result.GetAttributes(); | 4425 if (result.IsFound()) return result.GetAttributes(); |
4514 | 4426 |
4515 if (continue_search) { | 4427 if (check_prototype) { |
4516 // Continue searching via the prototype chain. | 4428 // Continue searching via the prototype chain. |
4517 Handle<Object> proto(object->GetPrototype(), isolate); | 4429 Handle<Object> proto(object->GetPrototype(), isolate); |
4518 if (!proto->IsNull()) { | 4430 if (!proto->IsNull()) { |
4519 return JSReceiver::GetPropertyAttributeWithReceiver( | 4431 return JSReceiver::GetPropertyAttributeWithReceiver( |
4520 Handle<JSObject>::cast(proto), receiver, name); | 4432 Handle<JSObject>::cast(proto), receiver, name); |
4521 } | 4433 } |
4522 } | 4434 } |
4523 return ABSENT; | 4435 return ABSENT; |
4524 } | 4436 } |
4525 | 4437 |
4526 | 4438 |
4527 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( | 4439 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( |
4528 Handle<JSObject> object, | 4440 Handle<JSObject> object, |
4529 Handle<JSObject> receiver, | 4441 Handle<JSObject> receiver, |
4530 Handle<Name> name, | 4442 Handle<Name> name, |
4531 bool continue_search) { | 4443 bool check_prototype) { |
4532 // TODO(rossberg): Support symbols in the API. | 4444 // TODO(rossberg): Support symbols in the API. |
4533 if (name->IsSymbol()) return ABSENT; | 4445 if (name->IsSymbol()) return ABSENT; |
4534 | 4446 |
4535 Isolate* isolate = object->GetIsolate(); | 4447 Isolate* isolate = object->GetIsolate(); |
4536 HandleScope scope(isolate); | 4448 HandleScope scope(isolate); |
4537 | 4449 |
4538 // Make sure that the top context does not change when doing | 4450 // Make sure that the top context does not change when doing |
4539 // callbacks or interceptor calls. | 4451 // callbacks or interceptor calls. |
4540 AssertNoContextChange ncc(isolate); | 4452 AssertNoContextChange ncc(isolate); |
4541 | 4453 |
(...skipping 14 matching lines...) Expand all Loading... |
4556 } else if (!interceptor->getter()->IsUndefined()) { | 4468 } else if (!interceptor->getter()->IsUndefined()) { |
4557 v8::NamedPropertyGetterCallback getter = | 4469 v8::NamedPropertyGetterCallback getter = |
4558 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 4470 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
4559 LOG(isolate, | 4471 LOG(isolate, |
4560 ApiNamedPropertyAccess("interceptor-named-get-has", *object, *name)); | 4472 ApiNamedPropertyAccess("interceptor-named-get-has", *object, *name)); |
4561 v8::Handle<v8::Value> result = | 4473 v8::Handle<v8::Value> result = |
4562 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4474 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
4563 if (!result.IsEmpty()) return DONT_ENUM; | 4475 if (!result.IsEmpty()) return DONT_ENUM; |
4564 } | 4476 } |
4565 return GetPropertyAttributePostInterceptor( | 4477 return GetPropertyAttributePostInterceptor( |
4566 object, receiver, name, continue_search); | 4478 object, receiver, name, check_prototype); |
4567 } | 4479 } |
4568 | 4480 |
4569 | 4481 |
4570 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( | 4482 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( |
4571 Handle<JSReceiver> object, | 4483 Handle<JSReceiver> object, |
4572 Handle<JSReceiver> receiver, | 4484 Handle<JSReceiver> receiver, |
4573 Handle<Name> key) { | 4485 Handle<Name> key) { |
4574 uint32_t index = 0; | 4486 uint32_t index = 0; |
4575 if (object->IsJSObject() && key->AsArrayIndex(&index)) { | 4487 if (object->IsJSObject() && key->AsArrayIndex(&index)) { |
4576 return JSObject::GetElementAttributeWithReceiver( | 4488 return JSObject::GetElementAttributeWithReceiver( |
4577 Handle<JSObject>::cast(object), receiver, index, true); | 4489 Handle<JSObject>::cast(object), receiver, index, true); |
4578 } | 4490 } |
4579 // Named property. | 4491 // Named property. |
4580 LookupResult lookup(object->GetIsolate()); | 4492 LookupResult lookup(object->GetIsolate()); |
4581 object->Lookup(key, &lookup); | 4493 object->Lookup(key, &lookup); |
4582 return GetPropertyAttributeForResult(object, receiver, &lookup, key, true); | 4494 return GetPropertyAttributeForResult(object, receiver, &lookup, key, true); |
4583 } | 4495 } |
4584 | 4496 |
4585 | 4497 |
4586 PropertyAttributes JSReceiver::GetPropertyAttributeForResult( | 4498 PropertyAttributes JSReceiver::GetPropertyAttributeForResult( |
4587 Handle<JSReceiver> object, | 4499 Handle<JSReceiver> object, |
4588 Handle<JSReceiver> receiver, | 4500 Handle<JSReceiver> receiver, |
4589 LookupResult* lookup, | 4501 LookupResult* lookup, |
4590 Handle<Name> name, | 4502 Handle<Name> name, |
4591 bool continue_search) { | 4503 bool check_prototype) { |
4592 // Check access rights if needed. | 4504 // Check access rights if needed. |
4593 if (object->IsAccessCheckNeeded()) { | 4505 if (object->IsAccessCheckNeeded()) { |
4594 Heap* heap = object->GetHeap(); | 4506 Heap* heap = object->GetHeap(); |
4595 Handle<JSObject> obj = Handle<JSObject>::cast(object); | 4507 Handle<JSObject> obj = Handle<JSObject>::cast(object); |
4596 if (!heap->isolate()->MayNamedAccess(obj, name, v8::ACCESS_HAS)) { | 4508 if (!heap->isolate()->MayNamedAccess(obj, name, v8::ACCESS_HAS)) { |
4597 return JSObject::GetPropertyAttributeWithFailedAccessCheck( | 4509 return JSObject::GetPropertyAttributeWithFailedAccessCheck( |
4598 obj, lookup, name, continue_search); | 4510 obj, lookup, name, check_prototype); |
4599 } | 4511 } |
4600 } | 4512 } |
4601 if (lookup->IsFound()) { | 4513 if (lookup->IsFound()) { |
4602 switch (lookup->type()) { | 4514 switch (lookup->type()) { |
4603 case NORMAL: // fall through | 4515 case NORMAL: // fall through |
4604 case FIELD: | 4516 case FIELD: |
4605 case CONSTANT: | 4517 case CONSTANT: |
4606 case CALLBACKS: | 4518 case CALLBACKS: |
4607 return lookup->GetAttributes(); | 4519 return lookup->GetAttributes(); |
4608 case HANDLER: { | 4520 case HANDLER: { |
4609 return JSProxy::GetPropertyAttributeWithHandler( | 4521 return JSProxy::GetPropertyAttributeWithHandler( |
4610 handle(lookup->proxy()), receiver, name); | 4522 handle(lookup->proxy()), receiver, name); |
4611 } | 4523 } |
4612 case INTERCEPTOR: | 4524 case INTERCEPTOR: |
4613 return JSObject::GetPropertyAttributeWithInterceptor( | 4525 return JSObject::GetPropertyAttributeWithInterceptor( |
4614 handle(lookup->holder()), | 4526 handle(lookup->holder()), |
4615 Handle<JSObject>::cast(receiver), | 4527 Handle<JSObject>::cast(receiver), |
4616 name, | 4528 name, |
4617 continue_search); | 4529 check_prototype); |
4618 case NONEXISTENT: | 4530 case NONEXISTENT: |
4619 UNREACHABLE(); | 4531 UNREACHABLE(); |
4620 } | 4532 } |
4621 } | 4533 } |
4622 return ABSENT; | 4534 return ABSENT; |
4623 } | 4535 } |
4624 | 4536 |
4625 | 4537 |
4626 PropertyAttributes JSReceiver::GetOwnPropertyAttribute( | 4538 PropertyAttributes JSReceiver::GetOwnPropertyAttribute( |
4627 Handle<JSReceiver> object, Handle<Name> name) { | 4539 Handle<JSReceiver> object, Handle<Name> name) { |
4628 // Check whether the name is an array index. | 4540 // Check whether the name is an array index. |
4629 uint32_t index = 0; | 4541 uint32_t index = 0; |
4630 if (object->IsJSObject() && name->AsArrayIndex(&index)) { | 4542 if (object->IsJSObject() && name->AsArrayIndex(&index)) { |
4631 return GetOwnElementAttribute(object, index); | 4543 return GetOwnElementAttribute(object, index); |
4632 } | 4544 } |
4633 // Named property. | 4545 // Named property. |
4634 LookupResult lookup(object->GetIsolate()); | 4546 LookupResult lookup(object->GetIsolate()); |
4635 object->LookupOwn(name, &lookup, true); | 4547 object->LookupOwn(name, &lookup, true); |
4636 return GetPropertyAttributeForResult(object, object, &lookup, name, false); | 4548 return GetPropertyAttributeForResult(object, object, &lookup, name, false); |
4637 } | 4549 } |
4638 | 4550 |
4639 | 4551 |
4640 PropertyAttributes JSObject::GetElementAttributeWithReceiver( | 4552 PropertyAttributes JSObject::GetElementAttributeWithReceiver( |
4641 Handle<JSObject> object, | 4553 Handle<JSObject> object, |
4642 Handle<JSReceiver> receiver, | 4554 Handle<JSReceiver> receiver, |
4643 uint32_t index, | 4555 uint32_t index, |
4644 bool continue_search) { | 4556 bool check_prototype) { |
4645 Isolate* isolate = object->GetIsolate(); | 4557 Isolate* isolate = object->GetIsolate(); |
4646 | 4558 |
4647 // Check access rights if needed. | 4559 // Check access rights if needed. |
4648 if (object->IsAccessCheckNeeded()) { | 4560 if (object->IsAccessCheckNeeded()) { |
4649 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { | 4561 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { |
4650 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 4562 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
4651 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 4563 // TODO(yangguo): Issue 3269, check for scheduled exception missing? |
4652 return ABSENT; | 4564 return ABSENT; |
4653 } | 4565 } |
4654 } | 4566 } |
4655 | 4567 |
4656 if (object->IsJSGlobalProxy()) { | 4568 if (object->IsJSGlobalProxy()) { |
4657 Handle<Object> proto(object->GetPrototype(), isolate); | 4569 Handle<Object> proto(object->GetPrototype(), isolate); |
4658 if (proto->IsNull()) return ABSENT; | 4570 if (proto->IsNull()) return ABSENT; |
4659 ASSERT(proto->IsJSGlobalObject()); | 4571 ASSERT(proto->IsJSGlobalObject()); |
4660 return JSObject::GetElementAttributeWithReceiver( | 4572 return JSObject::GetElementAttributeWithReceiver( |
4661 Handle<JSObject>::cast(proto), receiver, index, continue_search); | 4573 Handle<JSObject>::cast(proto), receiver, index, check_prototype); |
4662 } | 4574 } |
4663 | 4575 |
4664 // Check for lookup interceptor except when bootstrapping. | 4576 // Check for lookup interceptor except when bootstrapping. |
4665 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { | 4577 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { |
4666 return JSObject::GetElementAttributeWithInterceptor( | 4578 return JSObject::GetElementAttributeWithInterceptor( |
4667 object, receiver, index, continue_search); | 4579 object, receiver, index, check_prototype); |
4668 } | 4580 } |
4669 | 4581 |
4670 return GetElementAttributeWithoutInterceptor( | 4582 return GetElementAttributeWithoutInterceptor( |
4671 object, receiver, index, continue_search); | 4583 object, receiver, index, check_prototype); |
4672 } | 4584 } |
4673 | 4585 |
4674 | 4586 |
4675 PropertyAttributes JSObject::GetElementAttributeWithInterceptor( | 4587 PropertyAttributes JSObject::GetElementAttributeWithInterceptor( |
4676 Handle<JSObject> object, | 4588 Handle<JSObject> object, |
4677 Handle<JSReceiver> receiver, | 4589 Handle<JSReceiver> receiver, |
4678 uint32_t index, | 4590 uint32_t index, |
4679 bool continue_search) { | 4591 bool check_prototype) { |
4680 Isolate* isolate = object->GetIsolate(); | 4592 Isolate* isolate = object->GetIsolate(); |
4681 HandleScope scope(isolate); | 4593 HandleScope scope(isolate); |
4682 | 4594 |
4683 // Make sure that the top context does not change when doing | 4595 // Make sure that the top context does not change when doing |
4684 // callbacks or interceptor calls. | 4596 // callbacks or interceptor calls. |
4685 AssertNoContextChange ncc(isolate); | 4597 AssertNoContextChange ncc(isolate); |
4686 | 4598 |
4687 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | 4599 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
4688 PropertyCallbackArguments args( | 4600 PropertyCallbackArguments args( |
4689 isolate, interceptor->data(), *receiver, *object); | 4601 isolate, interceptor->data(), *receiver, *object); |
4690 if (!interceptor->query()->IsUndefined()) { | 4602 if (!interceptor->query()->IsUndefined()) { |
4691 v8::IndexedPropertyQueryCallback query = | 4603 v8::IndexedPropertyQueryCallback query = |
4692 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); | 4604 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
4693 LOG(isolate, | 4605 LOG(isolate, |
4694 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); | 4606 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); |
4695 v8::Handle<v8::Integer> result = args.Call(query, index); | 4607 v8::Handle<v8::Integer> result = args.Call(query, index); |
4696 if (!result.IsEmpty()) | 4608 if (!result.IsEmpty()) |
4697 return static_cast<PropertyAttributes>(result->Int32Value()); | 4609 return static_cast<PropertyAttributes>(result->Int32Value()); |
4698 } else if (!interceptor->getter()->IsUndefined()) { | 4610 } else if (!interceptor->getter()->IsUndefined()) { |
4699 v8::IndexedPropertyGetterCallback getter = | 4611 v8::IndexedPropertyGetterCallback getter = |
4700 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | 4612 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
4701 LOG(isolate, | 4613 LOG(isolate, |
4702 ApiIndexedPropertyAccess( | 4614 ApiIndexedPropertyAccess( |
4703 "interceptor-indexed-get-has", *object, index)); | 4615 "interceptor-indexed-get-has", *object, index)); |
4704 v8::Handle<v8::Value> result = args.Call(getter, index); | 4616 v8::Handle<v8::Value> result = args.Call(getter, index); |
4705 if (!result.IsEmpty()) return NONE; | 4617 if (!result.IsEmpty()) return NONE; |
4706 } | 4618 } |
4707 | 4619 |
4708 return GetElementAttributeWithoutInterceptor( | 4620 return GetElementAttributeWithoutInterceptor( |
4709 object, receiver, index, continue_search); | 4621 object, receiver, index, check_prototype); |
4710 } | 4622 } |
4711 | 4623 |
4712 | 4624 |
4713 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( | 4625 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( |
4714 Handle<JSObject> object, | 4626 Handle<JSObject> object, |
4715 Handle<JSReceiver> receiver, | 4627 Handle<JSReceiver> receiver, |
4716 uint32_t index, | 4628 uint32_t index, |
4717 bool continue_search) { | 4629 bool check_prototype) { |
4718 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( | 4630 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( |
4719 receiver, object, index); | 4631 receiver, object, index); |
4720 if (attr != ABSENT) return attr; | 4632 if (attr != ABSENT) return attr; |
4721 | 4633 |
4722 // Handle [] on String objects. | 4634 // Handle [] on String objects. |
4723 if (object->IsStringObjectWithCharacterAt(index)) { | 4635 if (object->IsStringObjectWithCharacterAt(index)) { |
4724 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); | 4636 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); |
4725 } | 4637 } |
4726 | 4638 |
4727 if (!continue_search) return ABSENT; | 4639 if (!check_prototype) return ABSENT; |
4728 | 4640 |
4729 Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); | 4641 Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); |
4730 if (proto->IsJSProxy()) { | 4642 if (proto->IsJSProxy()) { |
4731 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 4643 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
4732 return JSProxy::GetElementAttributeWithHandler( | 4644 return JSProxy::GetElementAttributeWithHandler( |
4733 Handle<JSProxy>::cast(proto), receiver, index); | 4645 Handle<JSProxy>::cast(proto), receiver, index); |
4734 } | 4646 } |
4735 if (proto->IsNull()) return ABSENT; | 4647 if (proto->IsNull()) return ABSENT; |
4736 return GetElementAttributeWithReceiver( | 4648 return GetElementAttributeWithReceiver( |
4737 Handle<JSObject>::cast(proto), receiver, index, true); | 4649 Handle<JSObject>::cast(proto), receiver, index, true); |
(...skipping 12558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17296 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17208 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17297 static const char* error_messages_[] = { | 17209 static const char* error_messages_[] = { |
17298 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17210 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17299 }; | 17211 }; |
17300 #undef ERROR_MESSAGES_TEXTS | 17212 #undef ERROR_MESSAGES_TEXTS |
17301 return error_messages_[reason]; | 17213 return error_messages_[reason]; |
17302 } | 17214 } |
17303 | 17215 |
17304 | 17216 |
17305 } } // namespace v8::internal | 17217 } } // namespace v8::internal |
OLD | NEW |