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

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: Addressed comments. 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
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());
2903 if (FLAG_harmony_observation && map()->is_observed()) { 2905 if (FLAG_harmony_observation && map()->is_observed()) {
2904 // TODO(observe): save oldValue 2906 old_value = handle(lookup->GetLazyValue());
2905 } 2907 }
2906 2908
2907 // This is a real property that is not read-only, or it is a 2909 // 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. 2910 // transition or null descriptor and there are no setters in the prototypes.
2909 MaybeObject* result = *value; 2911 MaybeObject* result = *value;
2910 switch (lookup->type()) { 2912 switch (lookup->type()) {
2911 case NORMAL: 2913 case NORMAL:
2912 result = self->SetNormalizedProperty(lookup, *value); 2914 result = self->SetNormalizedProperty(lookup, *value);
2913 break; 2915 break;
2914 case FIELD: 2916 case FIELD:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2946 if (attributes == details.attributes()) { 2948 if (attributes == details.attributes()) {
2947 int field_index = descriptors->GetFieldIndex(descriptor); 2949 int field_index = descriptors->GetFieldIndex(descriptor);
2948 result = self->AddFastPropertyUsingMap(transition_map, 2950 result = self->AddFastPropertyUsingMap(transition_map,
2949 *name, 2951 *name,
2950 *value, 2952 *value,
2951 field_index); 2953 field_index);
2952 } else { 2954 } else {
2953 result = self->ConvertDescriptorToField(*name, *value, attributes); 2955 result = self->ConvertDescriptorToField(*name, *value, attributes);
2954 } 2956 }
2955 } else if (details.type() == CALLBACKS) { 2957 } else if (details.type() == CALLBACKS) {
2956 result = ConvertDescriptorToField(*name, *value, attributes); 2958 result = self->ConvertDescriptorToField(*name, *value, attributes);
2957 } else { 2959 } else {
2958 ASSERT(details.type() == CONSTANT_FUNCTION); 2960 ASSERT(details.type() == CONSTANT_FUNCTION);
2959 2961
2960 Object* constant_function = descriptors->GetValue(descriptor); 2962 Object* constant_function = descriptors->GetValue(descriptor);
2961 if (constant_function == *value) { 2963 if (constant_function == *value) {
2962 // If the same constant function is being added we can simply 2964 // If the same constant function is being added we can simply
2963 // transition to the target map. 2965 // transition to the target map.
2964 self->set_map(transition_map); 2966 self->set_map(transition_map);
2965 result = constant_function; 2967 result = constant_function;
2966 } else { 2968 } else {
2967 // Otherwise, replace with a map transition to a new map with a FIELD, 2969 // Otherwise, replace with a map transition to a new map with a FIELD,
2968 // even if the value is a constant function. 2970 // even if the value is a constant function.
2969 result = ConvertTransitionToMapTransition( 2971 result = self->ConvertTransitionToMapTransition(
2970 lookup->GetTransitionIndex(), *name, *value, attributes); 2972 lookup->GetTransitionIndex(), *name, *value, attributes);
2971 } 2973 }
2972 } 2974 }
2973 break; 2975 break;
2974 } 2976 }
2975 case HANDLER: 2977 case HANDLER:
2976 case NONEXISTENT: 2978 case NONEXISTENT:
2977 UNREACHABLE(); 2979 UNREACHABLE();
2978 } 2980 }
2979 2981
2980 Handle<Object> hresult; 2982 Handle<Object> hresult;
2981 if (!result->ToHandle(&hresult)) return result; 2983 if (!result->ToHandle(&hresult)) return result;
2982 2984
2983 if (FLAG_harmony_observation && map()->is_observed()) { 2985 if (FLAG_harmony_observation && map()->is_observed()) {
2984 this->EnqueueChangeRecord("updated", name, old_value); 2986 if (lookup->IsTransition()) {
2987 self->EnqueueChangeRecord("new", name, old_value);
2988 } else {
2989 LookupResult new_lookup(self->GetIsolate());
2990 self->LocalLookup(*name, &new_lookup);
2991 ASSERT(!new_lookup.GetLazyValue()->IsTheHole());
2992 if (!new_lookup.GetLazyValue()->SameValue(*old_value)) {
2993 self->EnqueueChangeRecord("updated", name, old_value);
2994 }
2995 }
2985 } 2996 }
2986 2997
2987 return *hresult; 2998 return *hresult;
2988 } 2999 }
2989 3000
2990 3001
2991 // Set a real local property, even if it is READ_ONLY. If the property is not 3002 // 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 3003 // 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 3004 // SetProperty, with the check for IsReadOnly and the check for a
2994 // callback setter removed. The two lines looking up the LookupResult 3005 // callback setter removed. The two lines looking up the LookupResult
2995 // result are also added. If one of the functions is changed, the other 3006 // result are also added. If one of the functions is changed, the other
2996 // should be. 3007 // should be.
2997 // Note that this method cannot be used to set the prototype of a function 3008 // Note that this method cannot be used to set the prototype of a function
2998 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" 3009 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
2999 // doesn't handle function prototypes correctly. 3010 // doesn't handle function prototypes correctly.
3000 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( 3011 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
3001 Handle<JSObject> object, 3012 Handle<JSObject> object,
3002 Handle<String> key, 3013 Handle<String> key,
3003 Handle<Object> value, 3014 Handle<Object> value,
3004 PropertyAttributes attributes) { 3015 PropertyAttributes attributes) {
3005 CALL_HEAP_FUNCTION( 3016 CALL_HEAP_FUNCTION(
3006 object->GetIsolate(), 3017 object->GetIsolate(),
3007 object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes), 3018 object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
3008 Object); 3019 Object);
3009 } 3020 }
3010 3021
3011 3022
3012 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( 3023 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
3013 String* name, 3024 String* name_raw,
3014 Object* value, 3025 Object* value_raw,
3015 PropertyAttributes attributes) { 3026 PropertyAttributes attributes) {
3016 // Make sure that the top context does not change when doing callbacks or 3027 // Make sure that the top context does not change when doing callbacks or
3017 // interceptor calls. 3028 // interceptor calls.
3018 AssertNoContextChange ncc; 3029 AssertNoContextChange ncc;
3019 Isolate* isolate = GetIsolate(); 3030 Isolate* isolate = GetIsolate();
3020 LookupResult lookup(isolate); 3031 LookupResult lookup(isolate);
3021 LocalLookup(name, &lookup); 3032 LocalLookup(name_raw, &lookup);
3022 if (!lookup.IsFound()) map()->LookupTransition(this, name, &lookup); 3033 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup);
3023 // Check access rights if needed. 3034 // Check access rights if needed.
3024 if (IsAccessCheckNeeded()) { 3035 if (IsAccessCheckNeeded()) {
3025 if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 3036 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
3026 return SetPropertyWithFailedAccessCheck(&lookup, 3037 return SetPropertyWithFailedAccessCheck(&lookup,
3027 name, 3038 name_raw,
3028 value, 3039 value_raw,
3029 false, 3040 false,
3030 kNonStrictMode); 3041 kNonStrictMode);
3031 } 3042 }
3032 } 3043 }
3033 3044
3034 if (IsJSGlobalProxy()) { 3045 if (IsJSGlobalProxy()) {
3035 Object* proto = GetPrototype(); 3046 Object* proto = GetPrototype();
3036 if (proto->IsNull()) return value; 3047 if (proto->IsNull()) return value_raw;
3037 ASSERT(proto->IsJSGlobalObject()); 3048 ASSERT(proto->IsJSGlobalObject());
3038 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( 3049 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
3039 name, 3050 name_raw,
3040 value, 3051 value_raw,
3041 attributes); 3052 attributes);
3042 } 3053 }
3043 3054
3044 // Check for accessor in prototype chain removed here in clone. 3055 // Check for accessor in prototype chain removed here in clone.
3045 if (!lookup.IsFound()) { 3056 if (!lookup.IsFound()) {
3046 // Neither properties nor transitions found. 3057 // Neither properties nor transitions found.
3047 return AddProperty(name, value, attributes, kNonStrictMode); 3058 return AddProperty(name_raw, value_raw, attributes, kNonStrictMode);
3048 } 3059 }
3049 3060
3061 // From this point on everything needs to be handlified.
3062 HandleScope scope(GetIsolate());
3063 Handle<JSObject> self(this);
3064 Handle<String> name(name_raw);
3065 Handle<Object> value(value_raw);
3066
3050 Handle<Object> old_value(isolate->heap()->the_hole_value()); 3067 Handle<Object> old_value(isolate->heap()->the_hole_value());
3068 PropertyAttributes old_attributes;
3051 if (FLAG_harmony_observation && map()->is_observed()) { 3069 if (FLAG_harmony_observation && map()->is_observed()) {
3052 // TODO(observe): save oldValue 3070 old_value = handle(lookup.GetLazyValue());
3071 old_attributes = lookup.GetAttributes();
3053 } 3072 }
3054 3073
3055 // Check of IsReadOnly removed from here in clone. 3074 // Check of IsReadOnly removed from here in clone.
3056 MaybeObject* result = value; 3075 MaybeObject* result = *value;
3057 switch (lookup.type()) { 3076 switch (lookup.type()) {
3058 case NORMAL: { 3077 case NORMAL: {
3059 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3078 PropertyDetails details = PropertyDetails(attributes, NORMAL);
3060 result = SetNormalizedProperty(name, value, details); 3079 result = self->SetNormalizedProperty(*name, *value, details);
3061 break; 3080 break;
3062 } 3081 }
3063 case FIELD: 3082 case FIELD:
3064 result = FastPropertyAtPut(lookup.GetFieldIndex(), value); 3083 result = self->FastPropertyAtPut(lookup.GetFieldIndex(), *value);
3065 break; 3084 break;
3066 case CONSTANT_FUNCTION: 3085 case CONSTANT_FUNCTION:
3067 // Only replace the function if necessary. 3086 // Only replace the function if necessary.
3068 if (value == lookup.GetConstantFunction()) return value; 3087 if (*value != lookup.GetConstantFunction()) {
3069 // Preserve the attributes of this existing property. 3088 // Preserve the attributes of this existing property.
3070 attributes = lookup.GetAttributes(); 3089 attributes = lookup.GetAttributes();
3071 result = ConvertDescriptorToField(name, value, attributes); 3090 result = self->ConvertDescriptorToField(*name, *value, attributes);
3091 }
3072 break; 3092 break;
3073 case CALLBACKS: 3093 case CALLBACKS:
3074 case INTERCEPTOR: 3094 case INTERCEPTOR:
3075 // Override callback in clone 3095 // Override callback in clone
3076 result = ConvertDescriptorToField(name, value, attributes); 3096 result = self->ConvertDescriptorToField(*name, *value, attributes);
3077 break; 3097 break;
3078 case TRANSITION: { 3098 case TRANSITION: {
3079 Map* transition_map = lookup.GetTransitionTarget(); 3099 Map* transition_map = lookup.GetTransitionTarget();
3080 int descriptor = transition_map->LastAdded(); 3100 int descriptor = transition_map->LastAdded();
3081 3101
3082 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3102 DescriptorArray* descriptors = transition_map->instance_descriptors();
3083 PropertyDetails details = descriptors->GetDetails(descriptor); 3103 PropertyDetails details = descriptors->GetDetails(descriptor);
3084 3104
3085 if (details.type() == FIELD) { 3105 if (details.type() == FIELD) {
3086 if (attributes == details.attributes()) { 3106 if (attributes == details.attributes()) {
3087 int field_index = descriptors->GetFieldIndex(descriptor); 3107 int field_index = descriptors->GetFieldIndex(descriptor);
3088 result = AddFastPropertyUsingMap(transition_map, 3108 result = self->AddFastPropertyUsingMap(
3089 name, 3109 transition_map, *name, *value, field_index);
3090 value,
3091 field_index);
3092 } else { 3110 } else {
3093 result = ConvertDescriptorToField(name, value, attributes); 3111 result = self->ConvertDescriptorToField(*name, *value, attributes);
3094 } 3112 }
3095 } else if (details.type() == CALLBACKS) { 3113 } else if (details.type() == CALLBACKS) {
3096 result = ConvertDescriptorToField(name, value, attributes); 3114 result = self->ConvertDescriptorToField(*name, *value, attributes);
3097 } else { 3115 } else {
3098 ASSERT(details.type() == CONSTANT_FUNCTION); 3116 ASSERT(details.type() == CONSTANT_FUNCTION);
3099 3117
3100 // Replace transition to CONSTANT FUNCTION with a map transition to a 3118 // Replace transition to CONSTANT FUNCTION with a map transition to a
3101 // new map with a FIELD, even if the value is a function. 3119 // new map with a FIELD, even if the value is a function.
3102 result = ConvertTransitionToMapTransition( 3120 result = self->ConvertTransitionToMapTransition(
3103 lookup.GetTransitionIndex(), name, value, attributes); 3121 lookup.GetTransitionIndex(), *name, *value, attributes);
3104 } 3122 }
3105 break; 3123 break;
3106 } 3124 }
3107 case HANDLER: 3125 case HANDLER:
3108 case NONEXISTENT: 3126 case NONEXISTENT:
3109 UNREACHABLE(); 3127 UNREACHABLE();
3110 } 3128 }
3111 3129
3112 Handle<Object> hresult; 3130 Handle<Object> hresult;
3113 if (!result->ToHandle(&hresult)) return result; 3131 if (!result->ToHandle(&hresult)) return result;
3114 3132
3115 if (FLAG_harmony_observation && map()->is_observed()) { 3133 if (FLAG_harmony_observation && map()->is_observed()) {
3116 const char* type = 3134 if (lookup.IsTransition()) {
3117 attributes == lookup.GetAttributes() ? "updated" : "reconfigured"; 3135 self->EnqueueChangeRecord("new", name, old_value);
3118 this->EnqueueChangeRecord(type, handle(name), old_value); 3136 } else {
3137 LookupResult new_lookup(isolate);
3138 self->LocalLookup(*name, &new_lookup);
3139 ASSERT(!new_lookup.GetLazyValue()->IsTheHole());
3140 if (old_value->IsTheHole() ||
3141 new_lookup.GetAttributes() != old_attributes) {
3142 self->EnqueueChangeRecord("reconfigured", name, old_value);
3143 } else if (!new_lookup.GetLazyValue()->SameValue(*old_value)) {
3144 self->EnqueueChangeRecord("updated", name, old_value);
3145 }
3146 }
3119 } 3147 }
3120 3148
3121 return *hresult; 3149 return *hresult;
3122 } 3150 }
3123 3151
3124 3152
3125 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 3153 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3126 JSObject* receiver, 3154 JSObject* receiver,
3127 String* name, 3155 String* name,
3128 bool continue_search) { 3156 bool continue_search) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3196 3224
3197 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( 3225 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
3198 JSReceiver* receiver, 3226 JSReceiver* receiver,
3199 String* key) { 3227 String* key) {
3200 uint32_t index = 0; 3228 uint32_t index = 0;
3201 if (IsJSObject() && key->AsArrayIndex(&index)) { 3229 if (IsJSObject() && key->AsArrayIndex(&index)) {
3202 return JSObject::cast(this)->HasElementWithReceiver(receiver, index) 3230 return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3203 ? NONE : ABSENT; 3231 ? NONE : ABSENT;
3204 } 3232 }
3205 // Named property. 3233 // Named property.
3206 LookupResult result(GetIsolate()); 3234 LookupResult lookup(GetIsolate());
3207 Lookup(key, &result); 3235 Lookup(key, &lookup);
3208 return GetPropertyAttribute(receiver, &result, key, true); 3236 return GetPropertyAttributeForResult(receiver, &lookup, key, true);
3209 } 3237 }
3210 3238
3211 3239
3212 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, 3240 PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
3213 LookupResult* result, 3241 JSReceiver* receiver,
3214 String* name, 3242 LookupResult* lookup,
3215 bool continue_search) { 3243 String* name,
3244 bool continue_search) {
3216 // Check access rights if needed. 3245 // Check access rights if needed.
3217 if (IsAccessCheckNeeded()) { 3246 if (IsAccessCheckNeeded()) {
3218 JSObject* this_obj = JSObject::cast(this); 3247 JSObject* this_obj = JSObject::cast(this);
3219 Heap* heap = GetHeap(); 3248 Heap* heap = GetHeap();
3220 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) { 3249 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3221 return this_obj->GetPropertyAttributeWithFailedAccessCheck( 3250 return this_obj->GetPropertyAttributeWithFailedAccessCheck(
3222 receiver, result, name, continue_search); 3251 receiver, lookup, name, continue_search);
3223 } 3252 }
3224 } 3253 }
3225 if (result->IsFound()) { 3254 if (lookup->IsFound()) {
3226 switch (result->type()) { 3255 switch (lookup->type()) {
3227 case NORMAL: // fall through 3256 case NORMAL: // fall through
3228 case FIELD: 3257 case FIELD:
3229 case CONSTANT_FUNCTION: 3258 case CONSTANT_FUNCTION:
3230 case CALLBACKS: 3259 case CALLBACKS:
3231 return result->GetAttributes(); 3260 return lookup->GetAttributes();
3232 case HANDLER: { 3261 case HANDLER: {
3233 return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler( 3262 return JSProxy::cast(lookup->proxy())->GetPropertyAttributeWithHandler(
3234 receiver, name); 3263 receiver, name);
3235 } 3264 }
3236 case INTERCEPTOR: 3265 case INTERCEPTOR:
3237 return result->holder()->GetPropertyAttributeWithInterceptor( 3266 return lookup->holder()->GetPropertyAttributeWithInterceptor(
3238 JSObject::cast(receiver), name, continue_search); 3267 JSObject::cast(receiver), name, continue_search);
3239 case TRANSITION: 3268 case TRANSITION:
3240 case NONEXISTENT: 3269 case NONEXISTENT:
3241 UNREACHABLE(); 3270 UNREACHABLE();
3242 } 3271 }
3243 } 3272 }
3244 return ABSENT; 3273 return ABSENT;
3245 } 3274 }
3246 3275
3247 3276
3248 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { 3277 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
3249 // Check whether the name is an array index. 3278 // Check whether the name is an array index.
3250 uint32_t index = 0; 3279 uint32_t index = 0;
3251 if (IsJSObject() && name->AsArrayIndex(&index)) { 3280 if (IsJSObject() && name->AsArrayIndex(&index)) {
3252 if (JSObject::cast(this)->HasLocalElement(index)) return NONE; 3281 if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3253 return ABSENT; 3282 return ABSENT;
3254 } 3283 }
3255 // Named property. 3284 // Named property.
3256 LookupResult result(GetIsolate()); 3285 LookupResult lookup(GetIsolate());
3257 LocalLookup(name, &result); 3286 LocalLookup(name, &lookup);
3258 return GetPropertyAttribute(this, &result, name, false); 3287 return GetPropertyAttributeForResult(this, &lookup, name, false);
3259 } 3288 }
3260 3289
3261 3290
3262 MaybeObject* NormalizedMapCache::Get(JSObject* obj, 3291 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3263 PropertyNormalizationMode mode) { 3292 PropertyNormalizationMode mode) {
3264 Isolate* isolate = obj->GetIsolate(); 3293 Isolate* isolate = obj->GetIsolate();
3265 Map* fast = obj->map(); 3294 Map* fast = obj->map();
3266 int index = fast->Hash() % kEntries; 3295 int index = fast->Hash() % kEntries;
3267 Object* result = get(index); 3296 Object* result = get(index);
3268 if (result->IsMap() && 3297 if (result->IsMap() &&
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
4032 if (mode == STRICT_DELETION) { 4061 if (mode == STRICT_DELETION) {
4033 // Deleting a non-configurable property in strict mode. 4062 // Deleting a non-configurable property in strict mode.
4034 HandleScope scope(isolate); 4063 HandleScope scope(isolate);
4035 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; 4064 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
4036 return isolate->Throw(*isolate->factory()->NewTypeError( 4065 return isolate->Throw(*isolate->factory()->NewTypeError(
4037 "strict_delete_property", HandleVector(args, 2))); 4066 "strict_delete_property", HandleVector(args, 2)));
4038 } 4067 }
4039 return isolate->heap()->false_value(); 4068 return isolate->heap()->false_value();
4040 } 4069 }
4041 4070
4071 // From this point on everything needs to be handlified.
4042 HandleScope scope(isolate); 4072 HandleScope scope(isolate);
4073 Handle<JSObject> self(this);
4074 Handle<String> hname(name);
4075
4043 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4076 Handle<Object> old_value(isolate->heap()->the_hole_value());
4044 if (FLAG_harmony_observation && map()->is_observed()) { 4077 if (FLAG_harmony_observation && map()->is_observed()) {
4045 // TODO(observe): save oldValue 4078 old_value = handle(lookup.GetLazyValue());
4046 } 4079 }
4047 MaybeObject* result; 4080 MaybeObject* result;
4048 4081
4049 // Check for interceptor. 4082 // Check for interceptor.
4050 if (lookup.IsInterceptor()) { 4083 if (lookup.IsInterceptor()) {
4051 // Skip interceptor if forcing a deletion. 4084 // Skip interceptor if forcing a deletion.
4052 if (mode == FORCE_DELETION) { 4085 if (mode == FORCE_DELETION) {
4053 result = DeletePropertyPostInterceptor(name, mode); 4086 result = self->DeletePropertyPostInterceptor(*hname, mode);
4054 } else { 4087 } else {
4055 result = DeletePropertyWithInterceptor(name); 4088 result = self->DeletePropertyWithInterceptor(*hname);
4056 } 4089 }
4057 } else { 4090 } else {
4058 // Normalize object if needed. 4091 // Normalize object if needed.
4059 Object* obj; 4092 Object* obj;
4060 result = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 4093 result = self->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4061 if (!result->ToObject(&obj)) return result; 4094 if (!result->To(&obj)) return result;
4062 // Make sure the properties are normalized before removing the entry. 4095 // Make sure the properties are normalized before removing the entry.
4063 result = DeleteNormalizedProperty(name, mode); 4096 result = self->DeleteNormalizedProperty(*hname, mode);
4064 } 4097 }
4065 4098
4066 Handle<Object> hresult; 4099 Handle<Object> hresult;
4067 if (!result->ToHandle(&hresult)) return result; 4100 if (!result->ToHandle(&hresult)) return result;
4068 4101
4069 if (FLAG_harmony_observation && map()->is_observed()) { 4102 if (FLAG_harmony_observation && map()->is_observed()) {
4070 this->EnqueueChangeRecord("deleted", handle(name), old_value); 4103 if (!self->HasLocalProperty(*hname))
4104 self->EnqueueChangeRecord("deleted", hname, old_value);
4071 } 4105 }
4072 4106
4073 return *hresult; 4107 return *hresult;
4074 } 4108 }
4075 4109
4076 4110
4077 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { 4111 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
4078 if (IsJSProxy()) { 4112 if (IsJSProxy()) {
4079 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); 4113 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
4080 } 4114 }
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
4662 void JSObject::DefineAccessor(Handle<JSObject> object, 4696 void JSObject::DefineAccessor(Handle<JSObject> object,
4663 Handle<String> name, 4697 Handle<String> name,
4664 Handle<Object> getter, 4698 Handle<Object> getter,
4665 Handle<Object> setter, 4699 Handle<Object> setter,
4666 PropertyAttributes attributes) { 4700 PropertyAttributes attributes) {
4667 CALL_HEAP_FUNCTION_VOID( 4701 CALL_HEAP_FUNCTION_VOID(
4668 object->GetIsolate(), 4702 object->GetIsolate(),
4669 object->DefineAccessor(*name, *getter, *setter, attributes)); 4703 object->DefineAccessor(*name, *getter, *setter, attributes));
4670 } 4704 }
4671 4705
4672 MaybeObject* JSObject::DefineAccessor(String* name, 4706 MaybeObject* JSObject::DefineAccessor(String* name_raw,
4673 Object* getter, 4707 Object* getter_raw,
4674 Object* setter, 4708 Object* setter_raw,
4675 PropertyAttributes attributes) { 4709 PropertyAttributes attributes) {
4676 Isolate* isolate = GetIsolate(); 4710 Isolate* isolate = GetIsolate();
4677 // Check access rights if needed. 4711 // Check access rights if needed.
4678 if (IsAccessCheckNeeded() && 4712 if (IsAccessCheckNeeded() &&
4679 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4713 !isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
4680 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4714 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4681 return isolate->heap()->undefined_value(); 4715 return isolate->heap()->undefined_value();
4682 } 4716 }
4683 4717
4684 if (IsJSGlobalProxy()) { 4718 if (IsJSGlobalProxy()) {
4685 Object* proto = GetPrototype(); 4719 Object* proto = GetPrototype();
4686 if (proto->IsNull()) return this; 4720 if (proto->IsNull()) return this;
4687 ASSERT(proto->IsJSGlobalObject()); 4721 ASSERT(proto->IsJSGlobalObject());
4688 return JSObject::cast(proto)->DefineAccessor( 4722 return JSObject::cast(proto)->DefineAccessor(
4689 name, getter, setter, attributes); 4723 name_raw, getter_raw, setter_raw, attributes);
4690 } 4724 }
4691 4725
4692 // Make sure that the top context does not change when doing callbacks or 4726 // Make sure that the top context does not change when doing callbacks or
4693 // interceptor calls. 4727 // interceptor calls.
4694 AssertNoContextChange ncc; 4728 AssertNoContextChange ncc;
4695 4729
4696 // Try to flatten before operating on the string. 4730 // Try to flatten before operating on the string.
4697 name->TryFlatten(); 4731 name_raw->TryFlatten();
4698 4732
4699 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4733 if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value();
4734
4735 // From this point on everything needs to be handlified.
4736 HandleScope scope(GetIsolate());
4737 Handle<JSObject> self(this);
4738 Handle<String> name(name_raw);
4739 Handle<Object> getter(getter_raw);
4740 Handle<Object> setter(setter_raw);
4741
4742 uint32_t index = 0;
4743 bool is_element = name->AsArrayIndex(&index);
4700 4744
4701 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4745 Handle<Object> old_value(isolate->heap()->the_hole_value());
4702 bool preexists = false; 4746 bool preexists = false;
4703 if (FLAG_harmony_observation && map()->is_observed()) { 4747 if (FLAG_harmony_observation && map()->is_observed()) {
4704 LookupResult result(isolate); 4748 if (is_element) {
4705 LocalLookup(name, &result); 4749 preexists = HasLocalElement(index);
4706 preexists = result.IsFound(); 4750 if (preexists) {
4707 // TODO(observe): save oldValue 4751 // TODO(observe): distinguish the case where it's an accessor
4752 old_value = Object::GetElement(self, index);
4753 }
4754 } else {
4755 LookupResult lookup(isolate);
4756 LocalLookup(*name, &lookup);
4757 preexists = lookup.IsProperty();
4758 if (preexists) old_value = handle(lookup.GetLazyValue());
4759 }
4708 } 4760 }
4709 4761
4710 uint32_t index = 0; 4762 MaybeObject* result = is_element ?
4711 MaybeObject* result = name->AsArrayIndex(&index) 4763 self->DefineElementAccessor(index, *getter, *setter, attributes) :
4712 ? DefineElementAccessor(index, getter, setter, attributes) 4764 self->DefinePropertyAccessor(*name, *getter, *setter, attributes);
4713 : DefinePropertyAccessor(name, getter, setter, attributes);
4714 4765
4715 Handle<Object> hresult; 4766 Handle<Object> hresult;
4716 if (!result->ToHandle(&hresult)) return result; 4767 if (!result->ToHandle(&hresult)) return result;
4717 4768
4718 if (FLAG_harmony_observation && map()->is_observed()) { 4769 if (FLAG_harmony_observation && map()->is_observed()) {
4719 const char* type = preexists ? "reconfigured" : "new"; 4770 const char* type = preexists ? "reconfigured" : "new";
4720 this->EnqueueChangeRecord(type, handle(name), old_value); 4771 self->EnqueueChangeRecord(type, name, old_value);
4721 } 4772 }
4722 4773
4723 return *hresult; 4774 return *hresult;
4724 } 4775 }
4725 4776
4726 4777
4727 static MaybeObject* TryAccessorTransition(JSObject* self, 4778 static MaybeObject* TryAccessorTransition(JSObject* self,
4728 Map* transitioned_map, 4779 Map* transitioned_map,
4729 int target_descriptor, 4780 int target_descriptor,
4730 AccessorComponent component, 4781 AccessorComponent component,
(...skipping 8846 matching lines...) Expand 10 before | Expand all | Expand 10 after
13577 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13628 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13578 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13629 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13579 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13630 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13580 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13631 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13581 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13632 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13582 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13633 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13583 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13634 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13584 } 13635 }
13585 13636
13586 } } // namespace v8::internal 13637 } } // 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