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