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 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 | 781 |
782 // Lookup the property locally in the global object. If it isn't | 782 // Lookup the property locally in the global object. If it isn't |
783 // there, there is a property with this name in the prototype chain. | 783 // there, there is a property with this name in the prototype chain. |
784 // We follow Safari and Firefox behavior and only set the property | 784 // We follow Safari and Firefox behavior and only set the property |
785 // locally if there is an explicit initialization value that we have | 785 // locally if there is an explicit initialization value that we have |
786 // to assign to the property. When adding the property we take | 786 // to assign to the property. When adding the property we take |
787 // special precautions to always add it as a local property even in | 787 // special precautions to always add it as a local property even in |
788 // case of callbacks in the prototype chain (this rules out using | 788 // case of callbacks in the prototype chain (this rules out using |
789 // SetProperty). We have IgnoreAttributesAndSetLocalProperty for | 789 // SetProperty). We have IgnoreAttributesAndSetLocalProperty for |
790 // this. | 790 // this. |
| 791 // Note that objects can have hidden prototypes, so we need to traverse |
| 792 // the whole chain of hidden prototypes to do a 'local' lookup. |
| 793 JSObject* real_holder = global; |
791 LookupResult lookup; | 794 LookupResult lookup; |
792 global->LocalLookup(*name, &lookup); | 795 while (true) { |
793 if (!lookup.IsProperty()) { | 796 real_holder->LocalLookup(*name, &lookup); |
794 if (assign) { | 797 if (lookup.IsProperty()) { |
795 return global->IgnoreAttributesAndSetLocalProperty(*name, | 798 // Determine if this is a redeclaration of something read-only. |
796 args[1], | 799 if (lookup.IsReadOnly()) { |
797 attributes); | 800 // If we found readonly property on one of hidden prototypes, |
| 801 // just shadow it. |
| 802 if (real_holder != Top::context()->global()) break; |
| 803 return ThrowRedeclarationError("const", name); |
| 804 } |
| 805 |
| 806 // Determine if this is a redeclaration of an intercepted read-only |
| 807 // property and figure out if the property exists at all. |
| 808 bool found = true; |
| 809 PropertyType type = lookup.type(); |
| 810 if (type == INTERCEPTOR) { |
| 811 HandleScope handle_scope; |
| 812 Handle<JSObject> holder(real_holder); |
| 813 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); |
| 814 real_holder = *holder; |
| 815 if (intercepted == ABSENT) { |
| 816 // The interceptor claims the property isn't there. We need to |
| 817 // make sure to introduce it. |
| 818 found = false; |
| 819 } else if ((intercepted & READ_ONLY) != 0) { |
| 820 // The property is present, but read-only. Since we're trying to |
| 821 // overwrite it with a variable declaration we must throw a |
| 822 // re-declaration error. However if we found readonly property |
| 823 // on one of hidden prototypes, just shadow it. |
| 824 if (real_holder != Top::context()->global()) break; |
| 825 return ThrowRedeclarationError("const", name); |
| 826 } |
| 827 } |
| 828 |
| 829 if (found && !assign) { |
| 830 // The global property is there and we're not assigning any value |
| 831 // to it. Just return. |
| 832 return Heap::undefined_value(); |
| 833 } |
| 834 |
| 835 // Assign the value (or undefined) to the property. |
| 836 Object* value = (assign) ? args[1] : Heap::undefined_value(); |
| 837 return real_holder->SetProperty(&lookup, *name, value, attributes); |
798 } | 838 } |
799 return Heap::undefined_value(); | 839 |
| 840 Object* proto = real_holder->GetPrototype(); |
| 841 if (!proto->IsJSObject()) |
| 842 break; |
| 843 |
| 844 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) |
| 845 break; |
| 846 |
| 847 real_holder = JSObject::cast(proto); |
800 } | 848 } |
801 | 849 |
802 // Determine if this is a redeclaration of something read-only. | 850 global = Top::context()->global(); |
803 if (lookup.IsReadOnly()) { | 851 if (assign) { |
804 return ThrowRedeclarationError("const", name); | 852 return global->IgnoreAttributesAndSetLocalProperty(*name, |
| 853 args[1], |
| 854 attributes); |
805 } | 855 } |
806 | 856 return Heap::undefined_value(); |
807 // Determine if this is a redeclaration of an intercepted read-only | |
808 // property and figure out if the property exists at all. | |
809 bool found = true; | |
810 PropertyType type = lookup.type(); | |
811 if (type == INTERCEPTOR) { | |
812 PropertyAttributes intercepted = global->GetPropertyAttribute(*name); | |
813 if (intercepted == ABSENT) { | |
814 // The interceptor claims the property isn't there. We need to | |
815 // make sure to introduce it. | |
816 found = false; | |
817 } else if ((intercepted & READ_ONLY) != 0) { | |
818 // The property is present, but read-only. Since we're trying to | |
819 // overwrite it with a variable declaration we must throw a | |
820 // re-declaration error. | |
821 return ThrowRedeclarationError("const", name); | |
822 } | |
823 // Restore global object from context (in case of GC). | |
824 global = Top::context()->global(); | |
825 } | |
826 | |
827 if (found && !assign) { | |
828 // The global property is there and we're not assigning any value | |
829 // to it. Just return. | |
830 return Heap::undefined_value(); | |
831 } | |
832 | |
833 // Assign the value (or undefined) to the property. | |
834 Object* value = (assign) ? args[1] : Heap::undefined_value(); | |
835 return global->SetProperty(&lookup, *name, value, attributes); | |
836 } | 857 } |
837 | 858 |
838 | 859 |
839 static Object* Runtime_InitializeConstGlobal(Arguments args) { | 860 static Object* Runtime_InitializeConstGlobal(Arguments args) { |
840 // All constants are declared with an initial value. The name | 861 // All constants are declared with an initial value. The name |
841 // of the constant is the first argument and the initial value | 862 // of the constant is the first argument and the initial value |
842 // is the second. | 863 // is the second. |
843 RUNTIME_ASSERT(args.length() == 2); | 864 RUNTIME_ASSERT(args.length() == 2); |
844 CONVERT_ARG_CHECKED(String, name, 0); | 865 CONVERT_ARG_CHECKED(String, name, 0); |
845 Handle<Object> value = args.at<Object>(1); | 866 Handle<Object> value = args.at<Object>(1); |
(...skipping 7065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7911 } else { | 7932 } else { |
7912 // Handle last resort GC and make sure to allow future allocations | 7933 // Handle last resort GC and make sure to allow future allocations |
7913 // to grow the heap without causing GCs (if possible). | 7934 // to grow the heap without causing GCs (if possible). |
7914 Counters::gc_last_resort_from_js.Increment(); | 7935 Counters::gc_last_resort_from_js.Increment(); |
7915 Heap::CollectAllGarbage(false); | 7936 Heap::CollectAllGarbage(false); |
7916 } | 7937 } |
7917 } | 7938 } |
7918 | 7939 |
7919 | 7940 |
7920 } } // namespace v8::internal | 7941 } } // namespace v8::internal |
OLD | NEW |