Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: src/objects.cc

Issue 11362115: Object.observe: include oldValue in change records, (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 2743 matching lines...) Expand 10 before | Expand all | Expand 10 after
2754 2754
2755 int attributes = NONE; 2755 int attributes = NONE;
2756 if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM; 2756 if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2757 if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE; 2757 if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2758 if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY; 2758 if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2759 return static_cast<PropertyAttributes>(attributes); 2759 return static_cast<PropertyAttributes>(attributes);
2760 } 2760 }
2761 2761
2762 2762
2763 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler( 2763 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
2764 JSReceiver* receiver, 2764 JSReceiver* receiver_raw,
2765 uint32_t index) { 2765 uint32_t index) {
2766 Isolate* isolate = GetIsolate(); 2766 Isolate* isolate = GetIsolate();
2767 HandleScope scope(isolate); 2767 HandleScope scope(isolate);
2768 Handle<JSProxy> proxy(this);
2769 Handle<JSReceiver> receiver(receiver_raw);
2768 Handle<String> name = isolate->factory()->Uint32ToString(index); 2770 Handle<String> name = isolate->factory()->Uint32ToString(index);
2769 return GetPropertyAttributeWithHandler(receiver, *name); 2771 return proxy->GetPropertyAttributeWithHandler(*receiver, *name);
2770 } 2772 }
2771 2773
2772 2774
2773 void JSProxy::Fix() { 2775 void JSProxy::Fix() {
2774 Isolate* isolate = GetIsolate(); 2776 Isolate* isolate = GetIsolate();
2775 HandleScope scope(isolate); 2777 HandleScope scope(isolate);
2776 Handle<JSProxy> self(this); 2778 Handle<JSProxy> self(this);
2777 2779
2778 // Save identity hash. 2780 // Save identity hash.
2779 MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION); 2781 MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2893 if (strict_mode == kStrictMode) { 2895 if (strict_mode == kStrictMode) {
2894 Handle<Object> args[] = { name, self }; 2896 Handle<Object> args[] = { name, self };
2895 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( 2897 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2896 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); 2898 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2897 } else { 2899 } else {
2898 return *value; 2900 return *value;
2899 } 2901 }
2900 } 2902 }
2901 2903
2902 Handle<Object> old_value(heap->the_hole_value()); 2904 Handle<Object> old_value(heap->the_hole_value());
2905 PropertyAttributes old_attributes;
2903 if (FLAG_harmony_observation && map()->is_observed()) { 2906 if (FLAG_harmony_observation && map()->is_observed()) {
2904 // TODO(observe): save oldValue 2907 switch (lookup->type()) {
2908 case NORMAL:
2909 case FIELD:
2910 case CONSTANT_FUNCTION:
2911 case INTERCEPTOR:
adamk 2012/11/06 14:08:53 Asking for oldValues for interceptors (or in fact
rossberg 2012/11/07 14:05:54 Changed.
2912 old_value =
2913 Object::GetProperty(self, self, lookup, name, &old_attributes);
rafaelw 2012/11/07 10:26:20 Consider using lookup.GetLazyValue()? Note: this w
adamk 2012/11/07 10:30:29 Might also bypass access checks, though, which I d
rossberg 2012/11/07 14:05:54 Access checks are already handled further up, I th
rossberg 2012/11/07 14:05:54 Done, here and elsewhere. With a little tweak to t
2914 case CALLBACKS:
2915 case TRANSITION:
2916 case HANDLER:
2917 case NONEXISTENT:
2918 break;
2919 }
2905 } 2920 }
2906 2921
2907 // This is a real property that is not read-only, or it is a 2922 // This is a real property that is not read-only, or it is a
2908 // transition or null descriptor and there are no setters in the prototypes. 2923 // transition or null descriptor and there are no setters in the prototypes.
2909 MaybeObject* result = *value; 2924 MaybeObject* result = *value;
2910 switch (lookup->type()) { 2925 switch (lookup->type()) {
2911 case NORMAL: 2926 case NORMAL:
2912 result = self->SetNormalizedProperty(lookup, *value); 2927 result = self->SetNormalizedProperty(lookup, *value);
2913 break; 2928 break;
2914 case FIELD: 2929 case FIELD:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2946 if (attributes == details.attributes()) { 2961 if (attributes == details.attributes()) {
2947 int field_index = descriptors->GetFieldIndex(descriptor); 2962 int field_index = descriptors->GetFieldIndex(descriptor);
2948 result = self->AddFastPropertyUsingMap(transition_map, 2963 result = self->AddFastPropertyUsingMap(transition_map,
2949 *name, 2964 *name,
2950 *value, 2965 *value,
2951 field_index); 2966 field_index);
2952 } else { 2967 } else {
2953 result = self->ConvertDescriptorToField(*name, *value, attributes); 2968 result = self->ConvertDescriptorToField(*name, *value, attributes);
2954 } 2969 }
2955 } else if (details.type() == CALLBACKS) { 2970 } else if (details.type() == CALLBACKS) {
2956 result = ConvertDescriptorToField(*name, *value, attributes); 2971 result = ConvertDescriptorToField(*name, *value, attributes);
Toon Verwaest 2012/11/06 17:35:47 self->
rossberg 2012/11/07 14:05:54 Done.
2957 } else { 2972 } else {
2958 ASSERT(details.type() == CONSTANT_FUNCTION); 2973 ASSERT(details.type() == CONSTANT_FUNCTION);
2959 2974
2960 Object* constant_function = descriptors->GetValue(descriptor); 2975 Object* constant_function = descriptors->GetValue(descriptor);
2961 if (constant_function == *value) { 2976 if (constant_function == *value) {
2962 // If the same constant function is being added we can simply 2977 // If the same constant function is being added we can simply
2963 // transition to the target map. 2978 // transition to the target map.
2964 self->set_map(transition_map); 2979 self->set_map(transition_map);
2965 result = constant_function; 2980 result = constant_function;
2966 } else { 2981 } else {
2967 // Otherwise, replace with a map transition to a new map with a FIELD, 2982 // Otherwise, replace with a map transition to a new map with a FIELD,
2968 // even if the value is a constant function. 2983 // even if the value is a constant function.
2969 result = ConvertTransitionToMapTransition( 2984 result = ConvertTransitionToMapTransition(
Toon Verwaest 2012/11/06 17:35:47 self->
rossberg 2012/11/07 14:05:54 Done.
2970 lookup->GetTransitionIndex(), *name, *value, attributes); 2985 lookup->GetTransitionIndex(), *name, *value, attributes);
2971 } 2986 }
2972 } 2987 }
2973 break; 2988 break;
2974 } 2989 }
2975 case HANDLER: 2990 case HANDLER:
2976 case NONEXISTENT: 2991 case NONEXISTENT:
2977 UNREACHABLE(); 2992 UNREACHABLE();
2978 } 2993 }
2979 2994
2980 Handle<Object> hresult; 2995 Handle<Object> hresult;
2981 if (!result->ToHandle(&hresult)) return result; 2996 if (!result->ToHandle(&hresult)) return result;
2982 2997
2983 if (FLAG_harmony_observation && map()->is_observed()) { 2998 if (FLAG_harmony_observation && map()->is_observed()) {
2984 this->EnqueueChangeRecord("updated", name, old_value); 2999 PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name);
3000 if (lookup->IsTransition()) {
3001 self->EnqueueChangeRecord("new", name, old_value);
3002 } else if (new_attributes != old_attributes) {
rafaelw 2012/11/07 10:26:20 out of curiosity: how can it happen that new_attri
rossberg 2012/11/07 14:05:54 Right, I think it cannot in this case. Removed.
3003 self->EnqueueChangeRecord("reconfigured", name, old_value);
3004 } else {
3005 PropertyAttributes attributes;
3006 Handle<Object> new_value =
3007 Object::GetProperty(self, self, lookup, name, &attributes);
3008 if (!new_value->SameValue(*old_value))
3009 self->EnqueueChangeRecord("updated", name, old_value);
Toon Verwaest 2012/11/06 17:35:47 Wouldn't it be less error-prone to make EnqueueCha
rossberg 2012/11/07 14:05:54 Probably, but the same is true for quite a few oth
3010 }
2985 } 3011 }
2986 3012
2987 return *hresult; 3013 return *hresult;
2988 } 3014 }
2989 3015
2990 3016
2991 // Set a real local property, even if it is READ_ONLY. If the property is not 3017 // Set a real local property, even if it is READ_ONLY. If the property is not
2992 // present, add it with attributes NONE. This code is an exact clone of 3018 // present, add it with attributes NONE. This code is an exact clone of
2993 // SetProperty, with the check for IsReadOnly and the check for a 3019 // SetProperty, with the check for IsReadOnly and the check for a
2994 // callback setter removed. The two lines looking up the LookupResult 3020 // callback setter removed. The two lines looking up the LookupResult
2995 // result are also added. If one of the functions is changed, the other 3021 // result are also added. If one of the functions is changed, the other
2996 // should be. 3022 // should be.
2997 // Note that this method cannot be used to set the prototype of a function 3023 // Note that this method cannot be used to set the prototype of a function
2998 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" 3024 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
2999 // doesn't handle function prototypes correctly. 3025 // doesn't handle function prototypes correctly.
3000 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( 3026 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
3001 Handle<JSObject> object, 3027 Handle<JSObject> object,
3002 Handle<String> key, 3028 Handle<String> key,
3003 Handle<Object> value, 3029 Handle<Object> value,
3004 PropertyAttributes attributes) { 3030 PropertyAttributes attributes) {
3005 CALL_HEAP_FUNCTION( 3031 CALL_HEAP_FUNCTION(
3006 object->GetIsolate(), 3032 object->GetIsolate(),
3007 object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes), 3033 object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
3008 Object); 3034 Object);
3009 } 3035 }
3010 3036
3011 3037
3012 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( 3038 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
3013 String* name, 3039 String* name_raw,
3014 Object* value, 3040 Object* value_raw,
3015 PropertyAttributes attributes) { 3041 PropertyAttributes attributes) {
3016 // Make sure that the top context does not change when doing callbacks or 3042 // Make sure that the top context does not change when doing callbacks or
3017 // interceptor calls. 3043 // interceptor calls.
3018 AssertNoContextChange ncc; 3044 AssertNoContextChange ncc;
3019 Isolate* isolate = GetIsolate(); 3045 Isolate* isolate = GetIsolate();
3020 LookupResult lookup(isolate); 3046 LookupResult lookup(isolate);
3021 LocalLookup(name, &lookup); 3047 LocalLookup(name_raw, &lookup);
3022 if (!lookup.IsFound()) map()->LookupTransition(this, name, &lookup); 3048 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup);
3023 // Check access rights if needed. 3049 // Check access rights if needed.
3024 if (IsAccessCheckNeeded()) { 3050 if (IsAccessCheckNeeded()) {
3025 if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 3051 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
3026 return SetPropertyWithFailedAccessCheck(&lookup, 3052 return SetPropertyWithFailedAccessCheck(&lookup,
3027 name, 3053 name_raw,
3028 value, 3054 value_raw,
3029 false, 3055 false,
3030 kNonStrictMode); 3056 kNonStrictMode);
3031 } 3057 }
3032 } 3058 }
3033 3059
3034 if (IsJSGlobalProxy()) { 3060 if (IsJSGlobalProxy()) {
3035 Object* proto = GetPrototype(); 3061 Object* proto = GetPrototype();
3036 if (proto->IsNull()) return value; 3062 if (proto->IsNull()) return value_raw;
3037 ASSERT(proto->IsJSGlobalObject()); 3063 ASSERT(proto->IsJSGlobalObject());
3038 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( 3064 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
3039 name, 3065 name_raw,
3040 value, 3066 value_raw,
3041 attributes); 3067 attributes);
3042 } 3068 }
3043 3069
3044 // Check for accessor in prototype chain removed here in clone. 3070 // Check for accessor in prototype chain removed here in clone.
3045 if (!lookup.IsFound()) { 3071 if (!lookup.IsFound()) {
3046 // Neither properties nor transitions found. 3072 // Neither properties nor transitions found.
3047 return AddProperty(name, value, attributes, kNonStrictMode); 3073 return AddProperty(name_raw, value_raw, attributes, kNonStrictMode);
3048 } 3074 }
3049 3075
3076 // From this point on everything needs to be handlified.
3077 HandleScope scope(GetIsolate());
3078 Handle<JSObject> self(this);
3079 Handle<String> name(name_raw);
3080 Handle<Object> value(value_raw);
3081
3050 Handle<Object> old_value(isolate->heap()->the_hole_value()); 3082 Handle<Object> old_value(isolate->heap()->the_hole_value());
3083 PropertyAttributes old_attributes;
3051 if (FLAG_harmony_observation && map()->is_observed()) { 3084 if (FLAG_harmony_observation && map()->is_observed()) {
3052 // TODO(observe): save oldValue 3085 switch (lookup.type()) {
3086 case NORMAL:
3087 case FIELD:
3088 case CONSTANT_FUNCTION:
3089 case INTERCEPTOR:
3090 old_value =
3091 Object::GetProperty(self, self, &lookup, name, &old_attributes);
rafaelw 2012/11/07 10:26:20 ditto: GetLazyValue()
rossberg 2012/11/07 14:05:54 Done.
3092 case CALLBACKS:
3093 case TRANSITION:
3094 case HANDLER:
3095 case NONEXISTENT:
3096 break;
3097 }
3053 } 3098 }
3054 3099
3055 // Check of IsReadOnly removed from here in clone. 3100 // Check of IsReadOnly removed from here in clone.
3056 MaybeObject* result = value; 3101 MaybeObject* result = *value;
3057 switch (lookup.type()) { 3102 switch (lookup.type()) {
3058 case NORMAL: { 3103 case NORMAL: {
3059 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3104 PropertyDetails details = PropertyDetails(attributes, NORMAL);
3060 result = SetNormalizedProperty(name, value, details); 3105 result = self->SetNormalizedProperty(*name, *value, details);
3061 break; 3106 break;
3062 } 3107 }
3063 case FIELD: 3108 case FIELD:
3064 result = FastPropertyAtPut(lookup.GetFieldIndex(), value); 3109 result = self->FastPropertyAtPut(lookup.GetFieldIndex(), *value);
3065 break; 3110 break;
3066 case CONSTANT_FUNCTION: 3111 case CONSTANT_FUNCTION:
3067 // Only replace the function if necessary. 3112 // Only replace the function if necessary.
3068 if (value == lookup.GetConstantFunction()) return value; 3113 if (*value != lookup.GetConstantFunction()) {
3069 // Preserve the attributes of this existing property. 3114 // Preserve the attributes of this existing property.
3070 attributes = lookup.GetAttributes(); 3115 attributes = lookup.GetAttributes();
3071 result = ConvertDescriptorToField(name, value, attributes); 3116 result = self->ConvertDescriptorToField(*name, *value, attributes);
3117 }
3072 break; 3118 break;
3073 case CALLBACKS: 3119 case CALLBACKS:
3074 case INTERCEPTOR: 3120 case INTERCEPTOR:
3075 // Override callback in clone 3121 // Override callback in clone
3076 result = ConvertDescriptorToField(name, value, attributes); 3122 result = self->ConvertDescriptorToField(*name, *value, attributes);
3077 break; 3123 break;
3078 case TRANSITION: { 3124 case TRANSITION: {
3079 Map* transition_map = lookup.GetTransitionTarget(); 3125 Map* transition_map = lookup.GetTransitionTarget();
3080 int descriptor = transition_map->LastAdded(); 3126 int descriptor = transition_map->LastAdded();
3081 3127
3082 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3128 DescriptorArray* descriptors = transition_map->instance_descriptors();
3083 PropertyDetails details = descriptors->GetDetails(descriptor); 3129 PropertyDetails details = descriptors->GetDetails(descriptor);
3084 3130
3085 if (details.type() == FIELD) { 3131 if (details.type() == FIELD) {
3086 if (attributes == details.attributes()) { 3132 if (attributes == details.attributes()) {
3087 int field_index = descriptors->GetFieldIndex(descriptor); 3133 int field_index = descriptors->GetFieldIndex(descriptor);
3088 result = AddFastPropertyUsingMap(transition_map, 3134 result = self->AddFastPropertyUsingMap(
3089 name, 3135 transition_map, *name, *value, field_index);
3090 value,
3091 field_index);
3092 } else { 3136 } else {
3093 result = ConvertDescriptorToField(name, value, attributes); 3137 result = self->ConvertDescriptorToField(*name, *value, attributes);
3094 } 3138 }
3095 } else if (details.type() == CALLBACKS) { 3139 } else if (details.type() == CALLBACKS) {
3096 result = ConvertDescriptorToField(name, value, attributes); 3140 result = self->ConvertDescriptorToField(*name, *value, attributes);
3097 } else { 3141 } else {
3098 ASSERT(details.type() == CONSTANT_FUNCTION); 3142 ASSERT(details.type() == CONSTANT_FUNCTION);
3099 3143
3100 // Replace transition to CONSTANT FUNCTION with a map transition to a 3144 // Replace transition to CONSTANT FUNCTION with a map transition to a
3101 // new map with a FIELD, even if the value is a function. 3145 // new map with a FIELD, even if the value is a function.
3102 result = ConvertTransitionToMapTransition( 3146 result = self->ConvertTransitionToMapTransition(
3103 lookup.GetTransitionIndex(), name, value, attributes); 3147 lookup.GetTransitionIndex(), *name, *value, attributes);
3104 } 3148 }
3105 break; 3149 break;
3106 } 3150 }
3107 case HANDLER: 3151 case HANDLER:
3108 case NONEXISTENT: 3152 case NONEXISTENT:
3109 UNREACHABLE(); 3153 UNREACHABLE();
3110 } 3154 }
3111 3155
3112 Handle<Object> hresult; 3156 Handle<Object> hresult;
3113 if (!result->ToHandle(&hresult)) return result; 3157 if (!result->ToHandle(&hresult)) return result;
3114 3158
3115 if (FLAG_harmony_observation && map()->is_observed()) { 3159 if (FLAG_harmony_observation && map()->is_observed()) {
3116 const char* type = 3160 PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name);
3117 attributes == lookup.GetAttributes() ? "updated" : "reconfigured"; 3161 if (lookup.IsTransition()) {
3118 this->EnqueueChangeRecord(type, handle(name), old_value); 3162 self->EnqueueChangeRecord("new", name, old_value);
3163 } else if (new_attributes != old_attributes) {
3164 self->EnqueueChangeRecord("reconfigured", name, old_value);
3165 } else {
3166 Handle<Object> new_value =
3167 Object::GetProperty(self, self, &lookup, name, &old_attributes);
3168 if (!new_value->SameValue(*old_value))
3169 self->EnqueueChangeRecord("updated", name, old_value);
3170 }
3119 } 3171 }
3120 3172
3121 return *hresult; 3173 return *hresult;
3122 } 3174 }
3123 3175
3124 3176
3125 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 3177 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3126 JSObject* receiver, 3178 JSObject* receiver,
3127 String* name, 3179 String* name,
3128 bool continue_search) { 3180 bool continue_search) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3196 3248
3197 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( 3249 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
3198 JSReceiver* receiver, 3250 JSReceiver* receiver,
3199 String* key) { 3251 String* key) {
3200 uint32_t index = 0; 3252 uint32_t index = 0;
3201 if (IsJSObject() && key->AsArrayIndex(&index)) { 3253 if (IsJSObject() && key->AsArrayIndex(&index)) {
3202 return JSObject::cast(this)->HasElementWithReceiver(receiver, index) 3254 return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3203 ? NONE : ABSENT; 3255 ? NONE : ABSENT;
3204 } 3256 }
3205 // Named property. 3257 // Named property.
3206 LookupResult result(GetIsolate()); 3258 LookupResult lookup(GetIsolate());
3207 Lookup(key, &result); 3259 Lookup(key, &lookup);
3208 return GetPropertyAttribute(receiver, &result, key, true); 3260 return GetPropertyAttributeForResult(receiver, &lookup, key, true);
3209 } 3261 }
3210 3262
3211 3263
3212 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, 3264 PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
3213 LookupResult* result, 3265 JSReceiver* receiver,
3214 String* name, 3266 LookupResult* lookup,
3215 bool continue_search) { 3267 String* name,
3268 bool continue_search) {
3216 // Check access rights if needed. 3269 // Check access rights if needed.
3217 if (IsAccessCheckNeeded()) { 3270 if (IsAccessCheckNeeded()) {
3218 JSObject* this_obj = JSObject::cast(this); 3271 JSObject* this_obj = JSObject::cast(this);
3219 Heap* heap = GetHeap(); 3272 Heap* heap = GetHeap();
3220 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) { 3273 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3221 return this_obj->GetPropertyAttributeWithFailedAccessCheck( 3274 return this_obj->GetPropertyAttributeWithFailedAccessCheck(
3222 receiver, result, name, continue_search); 3275 receiver, lookup, name, continue_search);
3223 } 3276 }
3224 } 3277 }
3225 if (result->IsFound()) { 3278 if (lookup->IsFound()) {
3226 switch (result->type()) { 3279 switch (lookup->type()) {
3227 case NORMAL: // fall through 3280 case NORMAL: // fall through
3228 case FIELD: 3281 case FIELD:
3229 case CONSTANT_FUNCTION: 3282 case CONSTANT_FUNCTION:
3230 case CALLBACKS: 3283 case CALLBACKS:
3231 return result->GetAttributes(); 3284 return lookup->GetAttributes();
3232 case HANDLER: { 3285 case HANDLER: {
3233 return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler( 3286 return JSProxy::cast(lookup->proxy())->GetPropertyAttributeWithHandler(
3234 receiver, name); 3287 receiver, name);
3235 } 3288 }
3236 case INTERCEPTOR: 3289 case INTERCEPTOR:
3237 return result->holder()->GetPropertyAttributeWithInterceptor( 3290 return lookup->holder()->GetPropertyAttributeWithInterceptor(
3238 JSObject::cast(receiver), name, continue_search); 3291 JSObject::cast(receiver), name, continue_search);
3239 case TRANSITION: 3292 case TRANSITION:
3240 case NONEXISTENT: 3293 case NONEXISTENT:
3241 UNREACHABLE(); 3294 UNREACHABLE();
3242 } 3295 }
3243 } 3296 }
3244 return ABSENT; 3297 return ABSENT;
3245 } 3298 }
3246 3299
3247 3300
3248 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { 3301 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
3249 // Check whether the name is an array index. 3302 // Check whether the name is an array index.
3250 uint32_t index = 0; 3303 uint32_t index = 0;
3251 if (IsJSObject() && name->AsArrayIndex(&index)) { 3304 if (IsJSObject() && name->AsArrayIndex(&index)) {
3252 if (JSObject::cast(this)->HasLocalElement(index)) return NONE; 3305 if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3253 return ABSENT; 3306 return ABSENT;
3254 } 3307 }
3255 // Named property. 3308 // Named property.
3256 LookupResult result(GetIsolate()); 3309 LookupResult lookup(GetIsolate());
3257 LocalLookup(name, &result); 3310 LocalLookup(name, &lookup);
3258 return GetPropertyAttribute(this, &result, name, false); 3311 return GetPropertyAttributeForResult(this, &lookup, name, false);
3259 } 3312 }
3260 3313
3261 3314
3262 MaybeObject* NormalizedMapCache::Get(JSObject* obj, 3315 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3263 PropertyNormalizationMode mode) { 3316 PropertyNormalizationMode mode) {
3264 Isolate* isolate = obj->GetIsolate(); 3317 Isolate* isolate = obj->GetIsolate();
3265 Map* fast = obj->map(); 3318 Map* fast = obj->map();
3266 int index = fast->Hash() % kEntries; 3319 int index = fast->Hash() % kEntries;
3267 Object* result = get(index); 3320 Object* result = get(index);
3268 if (result->IsMap() && 3321 if (result->IsMap() &&
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
4032 if (mode == STRICT_DELETION) { 4085 if (mode == STRICT_DELETION) {
4033 // Deleting a non-configurable property in strict mode. 4086 // Deleting a non-configurable property in strict mode.
4034 HandleScope scope(isolate); 4087 HandleScope scope(isolate);
4035 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; 4088 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
4036 return isolate->Throw(*isolate->factory()->NewTypeError( 4089 return isolate->Throw(*isolate->factory()->NewTypeError(
4037 "strict_delete_property", HandleVector(args, 2))); 4090 "strict_delete_property", HandleVector(args, 2)));
4038 } 4091 }
4039 return isolate->heap()->false_value(); 4092 return isolate->heap()->false_value();
4040 } 4093 }
4041 4094
4095 // From this point on everything needs to be handlified.
4042 HandleScope scope(isolate); 4096 HandleScope scope(isolate);
4097 Handle<JSObject> self(this);
4098 Handle<String> hname(name);
4099
4043 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4100 Handle<Object> old_value(isolate->heap()->the_hole_value());
4044 if (FLAG_harmony_observation && map()->is_observed()) { 4101 if (FLAG_harmony_observation && map()->is_observed()) {
4045 // TODO(observe): save oldValue 4102 switch (lookup.type()) {
4103 case NORMAL:
4104 case FIELD:
4105 case CONSTANT_FUNCTION:
4106 case INTERCEPTOR: {
4107 PropertyAttributes old_attributes;
4108 old_value =
4109 Object::GetProperty(self, self, &lookup, hname, &old_attributes);
4110 }
4111 case CALLBACKS:
4112 case TRANSITION:
4113 case HANDLER:
4114 case NONEXISTENT:
4115 break;
4116 }
4046 } 4117 }
4047 MaybeObject* result; 4118 MaybeObject* result;
4048 4119
4049 // Check for interceptor. 4120 // Check for interceptor.
4050 if (lookup.IsInterceptor()) { 4121 if (lookup.IsInterceptor()) {
4051 // Skip interceptor if forcing a deletion. 4122 // Skip interceptor if forcing a deletion.
4052 if (mode == FORCE_DELETION) { 4123 if (mode == FORCE_DELETION) {
4053 result = DeletePropertyPostInterceptor(name, mode); 4124 result = self->DeletePropertyPostInterceptor(*hname, mode);
4054 } else { 4125 } else {
4055 result = DeletePropertyWithInterceptor(name); 4126 result = self->DeletePropertyWithInterceptor(*hname);
4056 } 4127 }
4057 } else { 4128 } else {
4058 // Normalize object if needed. 4129 // Normalize object if needed.
4059 Object* obj; 4130 Object* obj;
4060 result = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 4131 result = self->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4061 if (!result->ToObject(&obj)) return result; 4132 if (!result->To(&obj)) return result;
4062 // Make sure the properties are normalized before removing the entry. 4133 // Make sure the properties are normalized before removing the entry.
4063 result = DeleteNormalizedProperty(name, mode); 4134 result = self->DeleteNormalizedProperty(*hname, mode);
4064 } 4135 }
4065 4136
4066 Handle<Object> hresult; 4137 Handle<Object> hresult;
4067 if (!result->ToHandle(&hresult)) return result; 4138 if (!result->ToHandle(&hresult)) return result;
4068 4139
4069 if (FLAG_harmony_observation && map()->is_observed()) { 4140 if (FLAG_harmony_observation && map()->is_observed()) {
4070 this->EnqueueChangeRecord("deleted", handle(name), old_value); 4141 if (!self->HasLocalProperty(*hname))
4142 self->EnqueueChangeRecord("deleted", hname, old_value);
4071 } 4143 }
4072 4144
4073 return *hresult; 4145 return *hresult;
4074 } 4146 }
4075 4147
4076 4148
4077 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { 4149 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
4078 if (IsJSProxy()) { 4150 if (IsJSProxy()) {
4079 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); 4151 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
4080 } 4152 }
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
4662 void JSObject::DefineAccessor(Handle<JSObject> object, 4734 void JSObject::DefineAccessor(Handle<JSObject> object,
4663 Handle<String> name, 4735 Handle<String> name,
4664 Handle<Object> getter, 4736 Handle<Object> getter,
4665 Handle<Object> setter, 4737 Handle<Object> setter,
4666 PropertyAttributes attributes) { 4738 PropertyAttributes attributes) {
4667 CALL_HEAP_FUNCTION_VOID( 4739 CALL_HEAP_FUNCTION_VOID(
4668 object->GetIsolate(), 4740 object->GetIsolate(),
4669 object->DefineAccessor(*name, *getter, *setter, attributes)); 4741 object->DefineAccessor(*name, *getter, *setter, attributes));
4670 } 4742 }
4671 4743
4672 MaybeObject* JSObject::DefineAccessor(String* name, 4744 MaybeObject* JSObject::DefineAccessor(String* name_raw,
4673 Object* getter, 4745 Object* getter_raw,
4674 Object* setter, 4746 Object* setter_raw,
4675 PropertyAttributes attributes) { 4747 PropertyAttributes attributes) {
4676 Isolate* isolate = GetIsolate(); 4748 Isolate* isolate = GetIsolate();
4677 // Check access rights if needed. 4749 // Check access rights if needed.
4678 if (IsAccessCheckNeeded() && 4750 if (IsAccessCheckNeeded() &&
4679 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4751 !isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
4680 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4752 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4681 return isolate->heap()->undefined_value(); 4753 return isolate->heap()->undefined_value();
4682 } 4754 }
4683 4755
4684 if (IsJSGlobalProxy()) { 4756 if (IsJSGlobalProxy()) {
4685 Object* proto = GetPrototype(); 4757 Object* proto = GetPrototype();
4686 if (proto->IsNull()) return this; 4758 if (proto->IsNull()) return this;
4687 ASSERT(proto->IsJSGlobalObject()); 4759 ASSERT(proto->IsJSGlobalObject());
4688 return JSObject::cast(proto)->DefineAccessor( 4760 return JSObject::cast(proto)->DefineAccessor(
4689 name, getter, setter, attributes); 4761 name_raw, getter_raw, setter_raw, attributes);
4690 } 4762 }
4691 4763
4692 // Make sure that the top context does not change when doing callbacks or 4764 // Make sure that the top context does not change when doing callbacks or
4693 // interceptor calls. 4765 // interceptor calls.
4694 AssertNoContextChange ncc; 4766 AssertNoContextChange ncc;
4695 4767
4696 // Try to flatten before operating on the string. 4768 // Try to flatten before operating on the string.
4697 name->TryFlatten(); 4769 name_raw->TryFlatten();
4698 4770
4699 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4771 if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value();
4772
4773 // From this point on everything needs to be handlified.
4774 HandleScope scope(GetIsolate());
4775 Handle<JSObject> self(this);
4776 Handle<String> name(name_raw);
4777 Handle<Object> getter(getter_raw);
4778 Handle<Object> setter(setter_raw);
4779
4780 uint32_t index = 0;
4781 bool is_element = name->AsArrayIndex(&index);
4700 4782
4701 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4783 Handle<Object> old_value(isolate->heap()->the_hole_value());
4702 bool preexists = false; 4784 bool preexists = false;
4703 if (FLAG_harmony_observation && map()->is_observed()) { 4785 if (FLAG_harmony_observation && map()->is_observed()) {
4704 LookupResult result(isolate); 4786 if (is_element) {
4705 LocalLookup(name, &result); 4787 preexists = HasLocalElement(index);
4706 preexists = result.IsFound(); 4788 if (preexists) {
4707 // TODO(observe): save oldValue 4789 // TODO(observe): distinguish the case where it's an accessor
4790 old_value = Object::GetElement(self, index);
4791 }
4792 } else {
4793 LookupResult lookup(isolate);
4794 LocalLookup(*name, &lookup);
4795 preexists = lookup.IsProperty();
4796 if (preexists) {
4797 switch (lookup.type()) {
4798 case NORMAL:
4799 case FIELD:
4800 case CONSTANT_FUNCTION:
4801 case INTERCEPTOR: {
4802 PropertyAttributes old_attributes;
4803 old_value =
4804 Object::GetProperty(self, self, &lookup, name, &old_attributes);
4805 }
4806 case CALLBACKS:
4807 case TRANSITION:
4808 case HANDLER:
4809 case NONEXISTENT:
4810 break;
4811 }
4812 }
4813 }
4708 } 4814 }
4709 4815
4710 uint32_t index = 0; 4816 MaybeObject* result = is_element ?
4711 MaybeObject* result = name->AsArrayIndex(&index) 4817 self->DefineElementAccessor(index, *getter, *setter, attributes) :
4712 ? DefineElementAccessor(index, getter, setter, attributes) 4818 self->DefinePropertyAccessor(*name, *getter, *setter, attributes);
4713 : DefinePropertyAccessor(name, getter, setter, attributes);
4714 4819
4715 Handle<Object> hresult; 4820 Handle<Object> hresult;
4716 if (!result->ToHandle(&hresult)) return result; 4821 if (!result->ToHandle(&hresult)) return result;
4717 4822
4718 if (FLAG_harmony_observation && map()->is_observed()) { 4823 if (FLAG_harmony_observation && map()->is_observed()) {
4719 const char* type = preexists ? "reconfigured" : "new"; 4824 const char* type = preexists ? "reconfigured" : "new";
4720 this->EnqueueChangeRecord(type, handle(name), old_value); 4825 self->EnqueueChangeRecord(type, name, old_value);
4721 } 4826 }
4722 4827
4723 return *hresult; 4828 return *hresult;
4724 } 4829 }
4725 4830
4726 4831
4727 static MaybeObject* TryAccessorTransition(JSObject* self, 4832 static MaybeObject* TryAccessorTransition(JSObject* self,
4728 Map* transitioned_map, 4833 Map* transitioned_map,
4729 int target_descriptor, 4834 int target_descriptor,
4730 AccessorComponent component, 4835 AccessorComponent component,
(...skipping 8846 matching lines...) Expand 10 before | Expand all | Expand 10 after
13577 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13682 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13578 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13683 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13579 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13684 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13580 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13685 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13581 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13686 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13582 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13687 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13583 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13688 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13584 } 13689 }
13585 13690
13586 } } // namespace v8::internal 13691 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698