| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 if (!result->IsProperty()) { | 606 if (!result->IsProperty()) { |
| 607 Object* proto = obj->GetPrototype(); | 607 Object* proto = obj->GetPrototype(); |
| 608 if (proto->IsJSObject() && | 608 if (proto->IsJSObject() && |
| 609 JSObject::cast(proto)->map()->is_hidden_prototype()) | 609 JSObject::cast(proto)->map()->is_hidden_prototype()) |
| 610 GetOwnPropertyImplementation(JSObject::cast(proto), | 610 GetOwnPropertyImplementation(JSObject::cast(proto), |
| 611 name, result); | 611 name, result); |
| 612 } | 612 } |
| 613 } | 613 } |
| 614 | 614 |
| 615 | 615 |
| 616 static bool CheckAccessException(LookupResult* result, |
| 617 v8::AccessType access_type) { |
| 618 if (result->type() == CALLBACKS) { |
| 619 Object* callback = result->GetCallbackObject(); |
| 620 if (callback->IsAccessorInfo()) { |
| 621 AccessorInfo* info = AccessorInfo::cast(callback); |
| 622 bool can_access = |
| 623 (access_type == v8::ACCESS_HAS && |
| 624 (info->all_can_read() || info->all_can_write())) || |
| 625 (access_type == v8::ACCESS_GET && info->all_can_read()) || |
| 626 (access_type == v8::ACCESS_SET && info->all_can_write()); |
| 627 return can_access; |
| 628 } |
| 629 } |
| 630 |
| 631 return false; |
| 632 } |
| 633 |
| 634 |
| 635 static bool CheckAccess(JSObject* obj, |
| 636 String* name, |
| 637 LookupResult* result, |
| 638 v8::AccessType access_type) { |
| 639 ASSERT(result->IsProperty()); |
| 640 |
| 641 JSObject* holder = result->holder(); |
| 642 JSObject* current = obj; |
| 643 while (true) { |
| 644 if (current->IsAccessCheckNeeded() && |
| 645 !Top::MayNamedAccess(current, name, access_type)) { |
| 646 // Access check callback denied the access, but some properties |
| 647 // can have a special permissions which override callbacks descision |
| 648 // (currently see v8::AccessControl). |
| 649 break; |
| 650 } |
| 651 |
| 652 if (current == holder) { |
| 653 return true; |
| 654 } |
| 655 |
| 656 current = JSObject::cast(current->GetPrototype()); |
| 657 } |
| 658 |
| 659 // API callbacks can have per callback access exceptions. |
| 660 switch (result->type()) { |
| 661 case CALLBACKS: { |
| 662 if (CheckAccessException(result, access_type)) { |
| 663 return true; |
| 664 } |
| 665 break; |
| 666 } |
| 667 case INTERCEPTOR: { |
| 668 // If the object has an interceptor, try real named properties. |
| 669 // Overwrite the result to fetch the correct property later. |
| 670 holder->LookupRealNamedProperty(name, result); |
| 671 if (result->IsProperty()) { |
| 672 if (CheckAccessException(result, access_type)) { |
| 673 return true; |
| 674 } |
| 675 } |
| 676 break; |
| 677 } |
| 678 default: |
| 679 break; |
| 680 } |
| 681 |
| 682 Top::ReportFailedAccessCheck(current, access_type); |
| 683 return false; |
| 684 } |
| 685 |
| 686 |
| 687 // TODO(1095): we should traverse hidden prototype hierachy as well. |
| 688 static bool CheckElementAccess(JSObject* obj, |
| 689 uint32_t index, |
| 690 v8::AccessType access_type) { |
| 691 if (obj->IsAccessCheckNeeded() && |
| 692 !Top::MayIndexedAccess(obj, index, access_type)) { |
| 693 return false; |
| 694 } |
| 695 |
| 696 return true; |
| 697 } |
| 698 |
| 699 |
| 616 // Enumerator used as indices into the array returned from GetOwnProperty | 700 // Enumerator used as indices into the array returned from GetOwnProperty |
| 617 enum PropertyDescriptorIndices { | 701 enum PropertyDescriptorIndices { |
| 618 IS_ACCESSOR_INDEX, | 702 IS_ACCESSOR_INDEX, |
| 619 VALUE_INDEX, | 703 VALUE_INDEX, |
| 620 GETTER_INDEX, | 704 GETTER_INDEX, |
| 621 SETTER_INDEX, | 705 SETTER_INDEX, |
| 622 WRITABLE_INDEX, | 706 WRITABLE_INDEX, |
| 623 ENUMERABLE_INDEX, | 707 ENUMERABLE_INDEX, |
| 624 CONFIGURABLE_INDEX, | 708 CONFIGURABLE_INDEX, |
| 625 DESCRIPTOR_SIZE | 709 DESCRIPTOR_SIZE |
| (...skipping 22 matching lines...) Expand all Loading... |
| 648 case JSObject::UNDEFINED_ELEMENT: | 732 case JSObject::UNDEFINED_ELEMENT: |
| 649 return Heap::undefined_value(); | 733 return Heap::undefined_value(); |
| 650 | 734 |
| 651 case JSObject::STRING_CHARACTER_ELEMENT: { | 735 case JSObject::STRING_CHARACTER_ELEMENT: { |
| 652 // Special handling of string objects according to ECMAScript 5 | 736 // Special handling of string objects according to ECMAScript 5 |
| 653 // 15.5.5.2. Note that this might be a string object with elements | 737 // 15.5.5.2. Note that this might be a string object with elements |
| 654 // other than the actual string value. This is covered by the | 738 // other than the actual string value. This is covered by the |
| 655 // subsequent cases. | 739 // subsequent cases. |
| 656 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); | 740 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); |
| 657 Handle<String> str(String::cast(js_value->value())); | 741 Handle<String> str(String::cast(js_value->value())); |
| 658 Handle<String> substr = SubString(str, index, index+1, NOT_TENURED); | 742 Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); |
| 659 | 743 |
| 660 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 744 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 661 elms->set(VALUE_INDEX, *substr); | 745 elms->set(VALUE_INDEX, *substr); |
| 662 elms->set(WRITABLE_INDEX, Heap::false_value()); | 746 elms->set(WRITABLE_INDEX, Heap::false_value()); |
| 663 elms->set(ENUMERABLE_INDEX, Heap::false_value()); | 747 elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
| 664 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); | 748 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
| 665 return *desc; | 749 return *desc; |
| 666 } | 750 } |
| 667 | 751 |
| 668 case JSObject::INTERCEPTED_ELEMENT: | 752 case JSObject::INTERCEPTED_ELEMENT: |
| 669 case JSObject::FAST_ELEMENT: { | 753 case JSObject::FAST_ELEMENT: { |
| 670 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 754 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 671 Handle<Object> element = GetElement(Handle<Object>(obj), index); | 755 elms->set(VALUE_INDEX, *GetElement(obj, index)); |
| 672 elms->set(VALUE_INDEX, *element); | |
| 673 elms->set(WRITABLE_INDEX, Heap::true_value()); | 756 elms->set(WRITABLE_INDEX, Heap::true_value()); |
| 674 elms->set(ENUMERABLE_INDEX, Heap::true_value()); | 757 elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
| 675 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); | 758 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
| 676 return *desc; | 759 return *desc; |
| 677 } | 760 } |
| 678 | 761 |
| 679 case JSObject::DICTIONARY_ELEMENT: { | 762 case JSObject::DICTIONARY_ELEMENT: { |
| 680 NumberDictionary* dictionary = obj->element_dictionary(); | 763 Handle<JSObject> holder = obj; |
| 764 if (obj->IsJSGlobalProxy()) { |
| 765 Object* proto = obj->GetPrototype(); |
| 766 if (proto->IsNull()) return Heap::undefined_value(); |
| 767 ASSERT(proto->IsJSGlobalObject()); |
| 768 holder = Handle<JSObject>(JSObject::cast(proto)); |
| 769 } |
| 770 NumberDictionary* dictionary = holder->element_dictionary(); |
| 681 int entry = dictionary->FindEntry(index); | 771 int entry = dictionary->FindEntry(index); |
| 682 ASSERT(entry != NumberDictionary::kNotFound); | 772 ASSERT(entry != NumberDictionary::kNotFound); |
| 683 PropertyDetails details = dictionary->DetailsAt(entry); | 773 PropertyDetails details = dictionary->DetailsAt(entry); |
| 684 switch (details.type()) { | 774 switch (details.type()) { |
| 685 case CALLBACKS: { | 775 case CALLBACKS: { |
| 686 // This is an accessor property with getter and/or setter. | 776 // This is an accessor property with getter and/or setter. |
| 687 FixedArray* callbacks = | 777 FixedArray* callbacks = |
| 688 FixedArray::cast(dictionary->ValueAt(entry)); | 778 FixedArray::cast(dictionary->ValueAt(entry)); |
| 689 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | 779 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 690 elms->set(GETTER_INDEX, callbacks->get(0)); | 780 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { |
| 691 elms->set(SETTER_INDEX, callbacks->get(1)); | 781 elms->set(GETTER_INDEX, callbacks->get(0)); |
| 782 } |
| 783 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { |
| 784 elms->set(SETTER_INDEX, callbacks->get(1)); |
| 785 } |
| 692 break; | 786 break; |
| 693 } | 787 } |
| 694 case NORMAL: | 788 case NORMAL: |
| 695 // This is a data property. | 789 // This is a data property. |
| 696 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 790 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 697 elms->set(VALUE_INDEX, dictionary->ValueAt(entry)); | 791 elms->set(VALUE_INDEX, *GetElement(obj, index)); |
| 698 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); | 792 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); |
| 699 break; | 793 break; |
| 700 default: | 794 default: |
| 701 UNREACHABLE(); | 795 UNREACHABLE(); |
| 702 break; | 796 break; |
| 703 } | 797 } |
| 704 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); | 798 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
| 705 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); | 799 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
| 706 return *desc; | 800 return *desc; |
| 707 } | 801 } |
| 708 } | 802 } |
| 709 } | 803 } |
| 710 | 804 |
| 711 // Use recursive implementation to also traverse hidden prototypes | 805 // Use recursive implementation to also traverse hidden prototypes |
| 712 GetOwnPropertyImplementation(*obj, *name, &result); | 806 GetOwnPropertyImplementation(*obj, *name, &result); |
| 713 | 807 |
| 714 if (!result.IsProperty()) { | 808 if (!result.IsProperty()) { |
| 715 return Heap::undefined_value(); | 809 return Heap::undefined_value(); |
| 716 } | 810 } |
| 717 | 811 |
| 812 if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) { |
| 813 return Heap::false_value(); |
| 814 } |
| 815 |
| 718 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); | 816 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); |
| 719 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); | 817 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); |
| 720 | 818 |
| 721 bool is_js_accessor = (result.type() == CALLBACKS) && | 819 bool is_js_accessor = (result.type() == CALLBACKS) && |
| 722 (result.GetCallbackObject()->IsFixedArray()); | 820 (result.GetCallbackObject()->IsFixedArray()); |
| 723 | 821 |
| 724 if (is_js_accessor) { | 822 if (is_js_accessor) { |
| 725 // __defineGetter__/__defineSetter__ callback. | 823 // __defineGetter__/__defineSetter__ callback. |
| 824 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 825 |
| 726 FixedArray* structure = FixedArray::cast(result.GetCallbackObject()); | 826 FixedArray* structure = FixedArray::cast(result.GetCallbackObject()); |
| 727 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | 827 if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { |
| 728 elms->set(GETTER_INDEX, structure->get(0)); | 828 elms->set(GETTER_INDEX, structure->get(0)); |
| 729 elms->set(SETTER_INDEX, structure->get(1)); | 829 } |
| 830 if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { |
| 831 elms->set(SETTER_INDEX, structure->get(1)); |
| 832 } |
| 730 } else { | 833 } else { |
| 731 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 834 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 732 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); | 835 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
| 733 | 836 |
| 734 PropertyAttributes attrs; | 837 PropertyAttributes attrs; |
| 838 // GetProperty will check access and report any violations. |
| 735 Object* value = obj->GetProperty(*obj, &result, *name, &attrs); | 839 Object* value = obj->GetProperty(*obj, &result, *name, &attrs); |
| 736 if (value->IsFailure()) return value; | 840 if (value->IsFailure()) return value; |
| 737 elms->set(VALUE_INDEX, value); | 841 elms->set(VALUE_INDEX, value); |
| 738 } | 842 } |
| 739 | 843 |
| 740 return *desc; | 844 return *desc; |
| 741 } | 845 } |
| 742 | 846 |
| 743 | 847 |
| 744 static Object* Runtime_PreventExtensions(Arguments args) { | 848 static Object* Runtime_PreventExtensions(Arguments args) { |
| (...skipping 9407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10152 } else { | 10256 } else { |
| 10153 // Handle last resort GC and make sure to allow future allocations | 10257 // Handle last resort GC and make sure to allow future allocations |
| 10154 // to grow the heap without causing GCs (if possible). | 10258 // to grow the heap without causing GCs (if possible). |
| 10155 Counters::gc_last_resort_from_js.Increment(); | 10259 Counters::gc_last_resort_from_js.Increment(); |
| 10156 Heap::CollectAllGarbage(false); | 10260 Heap::CollectAllGarbage(false); |
| 10157 } | 10261 } |
| 10158 } | 10262 } |
| 10159 | 10263 |
| 10160 | 10264 |
| 10161 } } // namespace v8::internal | 10265 } } // namespace v8::internal |
| OLD | NEW |