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

Side by Side Diff: src/objects.cc

Issue 11365111: Object.observe: generate change records for indexed properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments; added/fixed missing bits of new elements functionality. 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
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:
2912 old_value =
2913 Object::GetProperty(self, self, lookup, name, &old_attributes);
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
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) {
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);
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);
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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3192 *name_handle, 3244 *name_handle,
3193 continue_search); 3245 continue_search);
3194 } 3246 }
3195 3247
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)->GetElementAttributeWithReceiver(
3203 ? NONE : ABSENT; 3255 receiver, index, true);
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 return GetLocalElementAttribute(index);
3253 return ABSENT;
3254 } 3306 }
3255 // Named property. 3307 // Named property.
3256 LookupResult result(GetIsolate()); 3308 LookupResult lookup(GetIsolate());
3257 LocalLookup(name, &result); 3309 LocalLookup(name, &lookup);
3258 return GetPropertyAttribute(this, &result, name, false); 3310 return GetPropertyAttributeForResult(this, &lookup, name, false);
3259 } 3311 }
3260 3312
3261 3313
3314 PropertyAttributes JSObject::GetElementAttributeWithReceiver(
3315 JSReceiver* receiver, uint32_t index, bool continue_search) {
3316 Isolate* isolate = GetIsolate();
3317
3318 // Check access rights if needed.
3319 if (IsAccessCheckNeeded()) {
3320 if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
3321 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
3322 return ABSENT;
3323 }
3324 }
3325
3326 if (IsJSGlobalProxy()) {
3327 Object* proto = GetPrototype();
3328 if (proto->IsNull()) return ABSENT;
3329 ASSERT(proto->IsJSGlobalObject());
3330 return JSReceiver::cast(proto)->GetLocalElementAttribute(index);
3331 }
3332
3333 // Check for lookup interceptor except when bootstrapping.
3334 if (HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
3335 return GetElementAttributeWithInterceptor(this, index, continue_search);
3336 }
3337
3338 return GetElementAttributeWithoutInterceptor(this, index, continue_search);
3339 }
3340
3341
3342 PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
3343 JSReceiver* receiver, uint32_t index, bool continue_search) {
3344 Isolate* isolate = GetIsolate();
3345 // Make sure that the top context does not change when doing
3346 // callbacks or interceptor calls.
3347 AssertNoContextChange ncc;
3348 HandleScope scope(isolate);
3349 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3350 Handle<JSReceiver> hreceiver(receiver);
3351 Handle<JSObject> holder(this);
3352 CustomArguments args(isolate, interceptor->data(), receiver, this);
3353 v8::AccessorInfo info(args.end());
3354 if (!interceptor->query()->IsUndefined()) {
3355 v8::IndexedPropertyQuery query =
3356 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
3357 LOG(isolate,
3358 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
3359 v8::Handle<v8::Integer> result;
3360 {
3361 // Leaving JavaScript.
3362 VMState state(isolate, EXTERNAL);
3363 result = query(index, info);
3364 }
3365 if (!result.IsEmpty())
3366 return static_cast<PropertyAttributes>(result->Int32Value());
3367 } else if (!interceptor->getter()->IsUndefined()) {
3368 v8::IndexedPropertyGetter getter =
3369 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
3370 LOG(isolate,
3371 ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index));
3372 v8::Handle<v8::Value> result;
3373 {
3374 // Leaving JavaScript.
3375 VMState state(isolate, EXTERNAL);
3376 result = getter(index, info);
3377 }
3378 if (!result.IsEmpty()) return DONT_ENUM;
3379 }
3380
3381 return holder->GetElementAttributeWithoutInterceptor(
3382 *hreceiver, index, continue_search);
3383 }
3384
3385
3386 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
3387 JSReceiver* receiver, uint32_t index, bool continue_search) {
3388 Isolate* isolate = GetIsolate();
3389 HandleScope scope(isolate);
3390 Handle<JSReceiver> hreceiver(receiver);
3391 Handle<JSObject> holder(this);
3392 PropertyAttributes attr = holder->GetElementsAccessor()->GetAttributes(
3393 *hreceiver, *holder, index);
3394 if (attr != ABSENT) return attr;
3395
3396 if (holder->IsStringObjectWithCharacterAt(index)) {
3397 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
3398 }
3399
3400 if (!continue_search) return ABSENT;
3401
3402 Object* pt = holder->GetPrototype();
3403 if (pt->IsJSProxy()) {
3404 // We need to follow the spec and simulate a call to [[GetOwnProperty]].
3405 return JSProxy::cast(pt)->GetElementAttributeWithHandler(*hreceiver, index);
3406 }
3407 if (pt->IsNull()) return ABSENT;
3408 return JSObject::cast(pt)->GetElementAttributeWithReceiver(
3409 *hreceiver, index, true);
3410 }
3411
3412
3262 MaybeObject* NormalizedMapCache::Get(JSObject* obj, 3413 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3263 PropertyNormalizationMode mode) { 3414 PropertyNormalizationMode mode) {
3264 Isolate* isolate = obj->GetIsolate(); 3415 Isolate* isolate = obj->GetIsolate();
3265 Map* fast = obj->map(); 3416 Map* fast = obj->map();
3266 int index = fast->Hash() % kEntries; 3417 int index = fast->Hash() % kEntries;
3267 Object* result = get(index); 3418 Object* result = get(index);
3268 if (result->IsMap() && 3419 if (result->IsMap() &&
3269 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { 3420 Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3270 #ifdef VERIFY_HEAP 3421 #ifdef VERIFY_HEAP
3271 if (FLAG_verify_heap) { 3422 if (FLAG_verify_heap) {
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
3973 return isolate->heap()->false_value(); 4124 return isolate->heap()->false_value();
3974 } 4125 }
3975 4126
3976 if (IsJSGlobalProxy()) { 4127 if (IsJSGlobalProxy()) {
3977 Object* proto = GetPrototype(); 4128 Object* proto = GetPrototype();
3978 if (proto->IsNull()) return isolate->heap()->false_value(); 4129 if (proto->IsNull()) return isolate->heap()->false_value();
3979 ASSERT(proto->IsJSGlobalObject()); 4130 ASSERT(proto->IsJSGlobalObject());
3980 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); 4131 return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3981 } 4132 }
3982 4133
3983 if (HasIndexedInterceptor()) { 4134 // From this point on everything needs to be handlified.
3984 // Skip interceptor if forcing deletion. 4135 HandleScope scope(isolate);
3985 if (mode != FORCE_DELETION) { 4136 Handle<JSObject> self(this);
3986 return DeleteElementWithInterceptor(index); 4137
4138 Handle<String> name;
4139 Handle<Object> old_value(isolate->heap()->the_hole_value());
4140 bool preexists = false;
4141 if (FLAG_harmony_observation && map()->is_observed()) {
4142 name = isolate->factory()->Uint32ToString(index);
4143 preexists = self->HasLocalElement(index);
4144 if (preexists) {
4145 // TODO(observe): only read & set old_value if it's not an accessor
4146 old_value = Object::GetElement(self, index);
3987 } 4147 }
3988 mode = JSReceiver::FORCE_DELETION;
3989 } 4148 }
3990 4149
3991 return GetElementsAccessor()->Delete(this, index, mode); 4150 MaybeObject* result;
4151 // Skip interceptor if forcing deletion.
4152 if (self->HasIndexedInterceptor() && mode != FORCE_DELETION) {
4153 result = self->DeleteElementWithInterceptor(index);
4154 } else {
4155 result = self->GetElementsAccessor()->Delete(*self, index, mode);
4156 }
4157
4158 Handle<Object> hresult;
4159 if (!result->ToHandle(&hresult)) return result;
4160
4161 if (FLAG_harmony_observation && map()->is_observed()) {
4162 if (preexists && !self->HasLocalElement(index))
4163 self->EnqueueChangeRecord("deleted", name, old_value);
4164 }
4165
4166 return *hresult;
3992 } 4167 }
3993 4168
3994 4169
3995 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, 4170 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
3996 Handle<String> prop) { 4171 Handle<String> prop) {
3997 CALL_HEAP_FUNCTION(obj->GetIsolate(), 4172 CALL_HEAP_FUNCTION(obj->GetIsolate(),
3998 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), 4173 obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
3999 Object); 4174 Object);
4000 } 4175 }
4001 4176
(...skipping 30 matching lines...) Expand all
4032 if (mode == STRICT_DELETION) { 4207 if (mode == STRICT_DELETION) {
4033 // Deleting a non-configurable property in strict mode. 4208 // Deleting a non-configurable property in strict mode.
4034 HandleScope scope(isolate); 4209 HandleScope scope(isolate);
4035 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; 4210 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
4036 return isolate->Throw(*isolate->factory()->NewTypeError( 4211 return isolate->Throw(*isolate->factory()->NewTypeError(
4037 "strict_delete_property", HandleVector(args, 2))); 4212 "strict_delete_property", HandleVector(args, 2)));
4038 } 4213 }
4039 return isolate->heap()->false_value(); 4214 return isolate->heap()->false_value();
4040 } 4215 }
4041 4216
4217 // From this point on everything needs to be handlified.
4042 HandleScope scope(isolate); 4218 HandleScope scope(isolate);
4219 Handle<JSObject> self(this);
4220 Handle<String> hname(name);
4221
4043 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4222 Handle<Object> old_value(isolate->heap()->the_hole_value());
4044 if (FLAG_harmony_observation && map()->is_observed()) { 4223 if (FLAG_harmony_observation && map()->is_observed()) {
4045 // TODO(observe): save oldValue 4224 switch (lookup.type()) {
4225 case NORMAL:
4226 case FIELD:
4227 case CONSTANT_FUNCTION:
4228 case INTERCEPTOR: {
4229 PropertyAttributes old_attributes;
4230 old_value =
4231 Object::GetProperty(self, self, &lookup, hname, &old_attributes);
4232 }
4233 case CALLBACKS:
4234 case TRANSITION:
4235 case HANDLER:
4236 case NONEXISTENT:
4237 break;
4238 }
4046 } 4239 }
4047 MaybeObject* result; 4240 MaybeObject* result;
4048 4241
4049 // Check for interceptor. 4242 // Check for interceptor.
4050 if (lookup.IsInterceptor()) { 4243 if (lookup.IsInterceptor()) {
4051 // Skip interceptor if forcing a deletion. 4244 // Skip interceptor if forcing a deletion.
4052 if (mode == FORCE_DELETION) { 4245 if (mode == FORCE_DELETION) {
4053 result = DeletePropertyPostInterceptor(name, mode); 4246 result = self->DeletePropertyPostInterceptor(*hname, mode);
4054 } else { 4247 } else {
4055 result = DeletePropertyWithInterceptor(name); 4248 result = self->DeletePropertyWithInterceptor(*hname);
4056 } 4249 }
4057 } else { 4250 } else {
4058 // Normalize object if needed. 4251 // Normalize object if needed.
4059 Object* obj; 4252 Object* obj;
4060 result = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 4253 result = self->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4061 if (!result->ToObject(&obj)) return result; 4254 if (!result->To(&obj)) return result;
4062 // Make sure the properties are normalized before removing the entry. 4255 // Make sure the properties are normalized before removing the entry.
4063 result = DeleteNormalizedProperty(name, mode); 4256 result = self->DeleteNormalizedProperty(*hname, mode);
4064 } 4257 }
4065 4258
4066 Handle<Object> hresult; 4259 Handle<Object> hresult;
4067 if (!result->ToHandle(&hresult)) return result; 4260 if (!result->ToHandle(&hresult)) return result;
4068 4261
4069 if (FLAG_harmony_observation && map()->is_observed()) { 4262 if (FLAG_harmony_observation && map()->is_observed()) {
4070 this->EnqueueChangeRecord("deleted", handle(name), old_value); 4263 if (!self->HasLocalProperty(*hname))
4264 self->EnqueueChangeRecord("deleted", hname, old_value);
4071 } 4265 }
4072 4266
4073 return *hresult; 4267 return *hresult;
4074 } 4268 }
4075 4269
4076 4270
4077 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { 4271 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
4078 if (IsJSProxy()) { 4272 if (IsJSProxy()) {
4079 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); 4273 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
4080 } 4274 }
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
4662 void JSObject::DefineAccessor(Handle<JSObject> object, 4856 void JSObject::DefineAccessor(Handle<JSObject> object,
4663 Handle<String> name, 4857 Handle<String> name,
4664 Handle<Object> getter, 4858 Handle<Object> getter,
4665 Handle<Object> setter, 4859 Handle<Object> setter,
4666 PropertyAttributes attributes) { 4860 PropertyAttributes attributes) {
4667 CALL_HEAP_FUNCTION_VOID( 4861 CALL_HEAP_FUNCTION_VOID(
4668 object->GetIsolate(), 4862 object->GetIsolate(),
4669 object->DefineAccessor(*name, *getter, *setter, attributes)); 4863 object->DefineAccessor(*name, *getter, *setter, attributes));
4670 } 4864 }
4671 4865
4672 MaybeObject* JSObject::DefineAccessor(String* name, 4866 MaybeObject* JSObject::DefineAccessor(String* name_raw,
4673 Object* getter, 4867 Object* getter_raw,
4674 Object* setter, 4868 Object* setter_raw,
4675 PropertyAttributes attributes) { 4869 PropertyAttributes attributes) {
4676 Isolate* isolate = GetIsolate(); 4870 Isolate* isolate = GetIsolate();
4677 // Check access rights if needed. 4871 // Check access rights if needed.
4678 if (IsAccessCheckNeeded() && 4872 if (IsAccessCheckNeeded() &&
4679 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4873 !isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
4680 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4874 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4681 return isolate->heap()->undefined_value(); 4875 return isolate->heap()->undefined_value();
4682 } 4876 }
4683 4877
4684 if (IsJSGlobalProxy()) { 4878 if (IsJSGlobalProxy()) {
4685 Object* proto = GetPrototype(); 4879 Object* proto = GetPrototype();
4686 if (proto->IsNull()) return this; 4880 if (proto->IsNull()) return this;
4687 ASSERT(proto->IsJSGlobalObject()); 4881 ASSERT(proto->IsJSGlobalObject());
4688 return JSObject::cast(proto)->DefineAccessor( 4882 return JSObject::cast(proto)->DefineAccessor(
4689 name, getter, setter, attributes); 4883 name_raw, getter_raw, setter_raw, attributes);
4690 } 4884 }
4691 4885
4692 // Make sure that the top context does not change when doing callbacks or 4886 // Make sure that the top context does not change when doing callbacks or
4693 // interceptor calls. 4887 // interceptor calls.
4694 AssertNoContextChange ncc; 4888 AssertNoContextChange ncc;
4695 4889
4696 // Try to flatten before operating on the string. 4890 // Try to flatten before operating on the string.
4697 name->TryFlatten(); 4891 name_raw->TryFlatten();
4698 4892
4699 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4893 if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value();
4894
4895 // From this point on everything needs to be handlified.
4896 HandleScope scope(GetIsolate());
4897 Handle<JSObject> self(this);
4898 Handle<String> name(name_raw);
4899 Handle<Object> getter(getter_raw);
4900 Handle<Object> setter(setter_raw);
4901
4902 uint32_t index = 0;
4903 bool is_element = name->AsArrayIndex(&index);
4700 4904
4701 Handle<Object> old_value(isolate->heap()->the_hole_value()); 4905 Handle<Object> old_value(isolate->heap()->the_hole_value());
4702 bool preexists = false; 4906 bool preexists = false;
4703 if (FLAG_harmony_observation && map()->is_observed()) { 4907 if (FLAG_harmony_observation && map()->is_observed()) {
4704 LookupResult result(isolate); 4908 if (is_element) {
4705 LocalLookup(name, &result); 4909 preexists = HasLocalElement(index);
4706 preexists = result.IsFound(); 4910 if (preexists) {
4707 // TODO(observe): save oldValue 4911 // TODO(observe): distinguish the case where it's an accessor
4912 old_value = Object::GetElement(self, index);
4913 }
4914 } else {
4915 LookupResult lookup(isolate);
4916 LocalLookup(*name, &lookup);
4917 preexists = lookup.IsProperty();
4918 if (preexists) {
4919 switch (lookup.type()) {
4920 case NORMAL:
4921 case FIELD:
4922 case CONSTANT_FUNCTION:
4923 case INTERCEPTOR: {
4924 PropertyAttributes old_attributes;
4925 old_value =
4926 Object::GetProperty(self, self, &lookup, name, &old_attributes);
4927 }
4928 case CALLBACKS:
4929 case TRANSITION:
4930 case HANDLER:
4931 case NONEXISTENT:
4932 break;
4933 }
4934 }
4935 }
4708 } 4936 }
4709 4937
4710 uint32_t index = 0; 4938 MaybeObject* result = is_element ?
4711 MaybeObject* result = name->AsArrayIndex(&index) 4939 self->DefineElementAccessor(index, *getter, *setter, attributes) :
4712 ? DefineElementAccessor(index, getter, setter, attributes) 4940 self->DefinePropertyAccessor(*name, *getter, *setter, attributes);
4713 : DefinePropertyAccessor(name, getter, setter, attributes);
4714 4941
4715 Handle<Object> hresult; 4942 Handle<Object> hresult;
4716 if (!result->ToHandle(&hresult)) return result; 4943 if (!result->ToHandle(&hresult)) return result;
4717 4944
4718 if (FLAG_harmony_observation && map()->is_observed()) { 4945 if (FLAG_harmony_observation && map()->is_observed()) {
4719 const char* type = preexists ? "reconfigured" : "new"; 4946 const char* type = preexists ? "reconfigured" : "new";
4720 this->EnqueueChangeRecord(type, handle(name), old_value); 4947 self->EnqueueChangeRecord(type, name, old_value);
4721 } 4948 }
4722 4949
4723 return *hresult; 4950 return *hresult;
4724 } 4951 }
4725 4952
4726 4953
4727 static MaybeObject* TryAccessorTransition(JSObject* self, 4954 static MaybeObject* TryAccessorTransition(JSObject* self,
4728 Map* transitioned_map, 4955 Map* transitioned_map,
4729 int target_descriptor, 4956 int target_descriptor,
4730 AccessorComponent component, 4957 AccessorComponent component,
(...skipping 5271 matching lines...) Expand 10 before | Expand all | Expand 10 after
10002 } 10229 }
10003 } 10230 }
10004 CALL_HEAP_FUNCTION( 10231 CALL_HEAP_FUNCTION(
10005 object->GetIsolate(), 10232 object->GetIsolate(),
10006 object->SetElement(index, *value, attr, strict_mode, true, set_mode), 10233 object->SetElement(index, *value, attr, strict_mode, true, set_mode),
10007 Object); 10234 Object);
10008 } 10235 }
10009 10236
10010 10237
10011 MaybeObject* JSObject::SetElement(uint32_t index, 10238 MaybeObject* JSObject::SetElement(uint32_t index,
10012 Object* value, 10239 Object* value_raw,
10013 PropertyAttributes attributes, 10240 PropertyAttributes attributes,
10014 StrictModeFlag strict_mode, 10241 StrictModeFlag strict_mode,
10015 bool check_prototype, 10242 bool check_prototype,
10016 SetPropertyMode set_mode) { 10243 SetPropertyMode set_mode) {
10244 Isolate* isolate = GetIsolate();
10245 HandleScope scope(isolate);
10246 Handle<JSObject> self(this);
10247 Handle<Object> value(value_raw);
10248
10017 // Check access rights if needed. 10249 // Check access rights if needed.
10018 if (IsAccessCheckNeeded()) { 10250 if (IsAccessCheckNeeded()) {
10019 Heap* heap = GetHeap(); 10251 Heap* heap = GetHeap();
10020 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { 10252 if (!heap->isolate()->MayIndexedAccess(*self, index, v8::ACCESS_SET)) {
10021 HandleScope scope(heap->isolate()); 10253 heap->isolate()->ReportFailedAccessCheck(*self, v8::ACCESS_SET);
10022 Handle<Object> value_handle(value); 10254 return *value;
10023 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
10024 return *value_handle;
10025 } 10255 }
10026 } 10256 }
10027 10257
10028 if (IsJSGlobalProxy()) { 10258 if (IsJSGlobalProxy()) {
10029 Object* proto = GetPrototype(); 10259 Object* proto = GetPrototype();
10030 if (proto->IsNull()) return value; 10260 if (proto->IsNull()) return *value;
10031 ASSERT(proto->IsJSGlobalObject()); 10261 ASSERT(proto->IsJSGlobalObject());
10032 return JSObject::cast(proto)->SetElement(index, 10262 return JSObject::cast(proto)->SetElement(index,
10033 value, 10263 *value,
10034 attributes, 10264 attributes,
10035 strict_mode, 10265 strict_mode,
10036 check_prototype, 10266 check_prototype,
10037 set_mode); 10267 set_mode);
10038 } 10268 }
10039 10269
10040 // Don't allow element properties to be redefined for external arrays. 10270 // Don't allow element properties to be redefined for external arrays.
10041 if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { 10271 if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
10042 Isolate* isolate = GetHeap()->isolate();
10043 Handle<Object> receiver(this);
10044 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 10272 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
10045 Handle<Object> args[] = { receiver, number }; 10273 Handle<Object> args[] = { self, number };
10046 Handle<Object> error = isolate->factory()->NewTypeError( 10274 Handle<Object> error = isolate->factory()->NewTypeError(
10047 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); 10275 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
10048 return isolate->Throw(*error); 10276 return isolate->Throw(*error);
10049 } 10277 }
10050 10278
10051 // Normalize the elements to enable attributes on the property. 10279 // Normalize the elements to enable attributes on the property.
10052 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { 10280 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
10053 SeededNumberDictionary* dictionary; 10281 SeededNumberDictionary* dictionary;
10054 MaybeObject* maybe_object = NormalizeElements(); 10282 MaybeObject* maybe_object = NormalizeElements();
10055 if (!maybe_object->To(&dictionary)) return maybe_object; 10283 if (!maybe_object->To(&dictionary)) return maybe_object;
10056 // Make sure that we never go back to fast case. 10284 // Make sure that we never go back to fast case.
10057 dictionary->set_requires_slow_elements(); 10285 dictionary->set_requires_slow_elements();
10058 } 10286 }
10059 10287
10060 // Check for lookup interceptor 10288 // From here on, everything has to be handlified.
10061 if (HasIndexedInterceptor()) { 10289 Handle<String> name;
10062 return SetElementWithInterceptor(index, 10290 Handle<Object> old_value(isolate->heap()->the_hole_value());
10063 value, 10291 PropertyAttributes old_attributes;
10064 attributes, 10292 bool preexists = false;
10065 strict_mode, 10293 if (FLAG_harmony_observation && map()->is_observed()) {
10066 check_prototype, 10294 name = isolate->factory()->Uint32ToString(index);
10067 set_mode); 10295 preexists = self->HasLocalElement(index);
10296 if (preexists) {
10297 old_attributes = self->GetLocalPropertyAttribute(*name);
10298 // TODO(observe): only read & set old_value if we have a data property
10299 old_value = Object::GetElement(self, index);
10300 }
10068 } 10301 }
10069 10302
10070 return SetElementWithoutInterceptor(index, 10303 // Check for lookup interceptor
10071 value, 10304 MaybeObject* result = self->HasIndexedInterceptor()
10072 attributes, 10305 ? self->SetElementWithInterceptor(
10073 strict_mode, 10306 index, *value, attributes, strict_mode, check_prototype, set_mode)
10074 check_prototype, 10307 : self->SetElementWithoutInterceptor(
10075 set_mode); 10308 index, *value, attributes, strict_mode, check_prototype, set_mode);
10309
10310 Handle<Object> hresult;
10311 if (!result->ToHandle(&hresult)) return result;
10312
10313 if (FLAG_harmony_observation && map()->is_observed()) {
10314 PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name);
10315 if (!preexists) {
10316 self->EnqueueChangeRecord("new", name, old_value);
10317 } else if (new_attributes != old_attributes || old_value->IsTheHole()) {
10318 self->EnqueueChangeRecord("reconfigured", name, old_value);
10319 } else {
10320 Handle<Object> newValue = Object::GetElement(self, index);
10321 if (!newValue->SameValue(*old_value))
10322 self->EnqueueChangeRecord("updated", name, old_value);
10323 }
10324 }
10325
10326 return *hresult;
10076 } 10327 }
10077 10328
10078 10329
10079 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 10330 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
10080 Object* value, 10331 Object* value,
10081 PropertyAttributes attr, 10332 PropertyAttributes attr,
10082 StrictModeFlag strict_mode, 10333 StrictModeFlag strict_mode,
10083 bool check_prototype, 10334 bool check_prototype,
10084 SetPropertyMode set_mode) { 10335 SetPropertyMode set_mode) {
10085 ASSERT(HasDictionaryElements() || 10336 ASSERT(HasDictionaryElements() ||
(...skipping 3491 matching lines...) Expand 10 before | Expand all | Expand 10 after
13577 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13828 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13578 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13829 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13579 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13830 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13580 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13831 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13581 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13832 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13582 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13833 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13583 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13834 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13584 } 13835 }
13585 13836
13586 } } // namespace v8::internal 13837 } } // namespace v8::internal
OLDNEW
« src/elements.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698