| OLD | NEW | 
|      1 // Copyright 2013 the V8 project authors. All rights reserved. |      1 // Copyright 2013 the V8 project authors. All rights reserved. | 
|      2 // Use of this source code is governed by a BSD-style license that can be |      2 // Use of this source code is governed by a BSD-style license that can be | 
|      3 // found in the LICENSE file. |      3 // found in the LICENSE file. | 
|      4  |      4  | 
|      5 #include "src/v8.h" |      5 #include "src/v8.h" | 
|      6  |      6  | 
|      7 #include "src/accessors.h" |      7 #include "src/accessors.h" | 
|      8 #include "src/allocation-site-scopes.h" |      8 #include "src/allocation-site-scopes.h" | 
|      9 #include "src/api.h" |      9 #include "src/api.h" | 
|     10 #include "src/arguments.h" |     10 #include "src/arguments.h" | 
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    455   if (getter->IsSpecFunction()) { |    455   if (getter->IsSpecFunction()) { | 
|    456     // TODO(rossberg): nicer would be to cast to some JSCallable here... |    456     // TODO(rossberg): nicer would be to cast to some JSCallable here... | 
|    457     return Object::GetPropertyWithDefinedGetter( |    457     return Object::GetPropertyWithDefinedGetter( | 
|    458         receiver, Handle<JSReceiver>::cast(getter)); |    458         receiver, Handle<JSReceiver>::cast(getter)); | 
|    459   } |    459   } | 
|    460   // Getter is not a function. |    460   // Getter is not a function. | 
|    461   return isolate->factory()->undefined_value(); |    461   return isolate->factory()->undefined_value(); | 
|    462 } |    462 } | 
|    463  |    463  | 
|    464  |    464  | 
|    465 MaybeHandle<Object> Object::SetPropertyWithCallback(Handle<Object> receiver, |    465 MaybeHandle<Object> Object::SetPropertyWithAccessor( | 
|    466                                                     Handle<Name> name, |    466     Handle<Object> receiver, Handle<Name> name, Handle<Object> value, | 
|    467                                                     Handle<Object> value, |    467     Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) { | 
|    468                                                     Handle<JSObject> holder, |  | 
|    469                                                     Handle<Object> structure, |  | 
|    470                                                     StrictMode strict_mode) { |  | 
|    471   Isolate* isolate = name->GetIsolate(); |    468   Isolate* isolate = name->GetIsolate(); | 
|    472  |    469  | 
|    473   // We should never get here to initialize a const with the hole |    470   // We should never get here to initialize a const with the hole | 
|    474   // value since a const declaration would conflict with the setter. |    471   // value since a const declaration would conflict with the setter. | 
|    475   ASSERT(!structure->IsForeign()); |    472   ASSERT(!structure->IsForeign()); | 
|    476   if (structure->IsExecutableAccessorInfo()) { |    473   if (structure->IsExecutableAccessorInfo()) { | 
|    477     // api style callbacks |    474     // api style callbacks | 
|    478     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); |    475     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); | 
|    479     if (!data->IsCompatibleReceiver(*receiver)) { |    476     if (!data->IsCompatibleReceiver(*receiver)) { | 
|    480       Handle<Object> args[2] = { name, receiver }; |    477       Handle<Object> args[2] = { name, receiver }; | 
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    598 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck( |    595 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck( | 
|    599     LookupIterator* it) { |    596     LookupIterator* it) { | 
|    600   Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder()); |    597   Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder()); | 
|    601   if (FindAllCanReadHolder(it)) return it->property_details().attributes(); |    598   if (FindAllCanReadHolder(it)) return it->property_details().attributes(); | 
|    602   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); |    599   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); | 
|    603   // TODO(yangguo): Issue 3269, check for scheduled exception missing? |    600   // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 
|    604   return ABSENT; |    601   return ABSENT; | 
|    605 } |    602 } | 
|    606  |    603  | 
|    607  |    604  | 
|    608 static bool FindAllCanWriteHolder(LookupResult* result, |    605 static bool FindAllCanWriteHolder(LookupIterator* it) { | 
|    609                                   Handle<Name> name, |    606   it->skip_interceptor(); | 
|    610                                   bool check_prototype) { |    607   it->skip_access_check(); | 
|    611   if (result->IsInterceptor()) { |    608   for (; it->IsFound(); it->Next()) { | 
|    612     result->holder()->LookupOwnRealNamedProperty(name, result); |    609     if (it->state() == LookupIterator::PROPERTY && it->HasProperty() && | 
|    613   } |    610         it->property_kind() == LookupIterator::ACCESSOR) { | 
|    614  |    611       Handle<Object> accessors = it->GetAccessors(); | 
|    615   while (result->IsProperty()) { |    612       if (accessors->IsAccessorInfo()) { | 
|    616     if (result->type() == CALLBACKS) { |    613         if (AccessorInfo::cast(*accessors)->all_can_write()) return true; | 
|    617       Object* callback_obj = result->GetCallbackObject(); |  | 
|    618       if (callback_obj->IsAccessorInfo()) { |  | 
|    619         if (AccessorInfo::cast(callback_obj)->all_can_write()) return true; |  | 
|    620       } |    614       } | 
|    621     } |    615     } | 
|    622     if (!check_prototype) break; |  | 
|    623     result->holder()->LookupRealNamedPropertyInPrototypes(name, result); |  | 
|    624   } |    616   } | 
|    625   return false; |    617   return false; | 
|    626 } |    618 } | 
|    627  |    619  | 
|    628  |    620  | 
|    629 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( |    621 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( | 
|    630     Handle<JSObject> object, |    622     LookupIterator* it, Handle<Object> value, StrictMode strict_mode) { | 
|    631     LookupResult* result, |    623   Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder()); | 
|    632     Handle<Name> name, |    624   if (FindAllCanWriteHolder(it)) { | 
|    633     Handle<Object> value, |    625     return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value, | 
|    634     bool check_prototype, |    626                                    it->GetHolder(), it->GetAccessors(), | 
|    635     StrictMode strict_mode) { |    627                                    strict_mode); | 
|    636   if (check_prototype && !result->IsProperty()) { |  | 
|    637     object->LookupRealNamedPropertyInPrototypes(name, result); |  | 
|    638   } |    628   } | 
|    639  |    629  | 
|    640   if (FindAllCanWriteHolder(result, name, check_prototype)) { |    630   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET); | 
|    641     Handle<JSObject> holder(result->holder()); |    631   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 
|    642     Handle<Object> callbacks(result->GetCallbackObject(), result->isolate()); |  | 
|    643     return SetPropertyWithCallback( |  | 
|    644         object, name, value, holder, callbacks, strict_mode); |  | 
|    645   } |  | 
|    646  |  | 
|    647   Isolate* isolate = object->GetIsolate(); |  | 
|    648   isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |  | 
|    649   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |  | 
|    650   return value; |    632   return value; | 
|    651 } |    633 } | 
|    652  |    634  | 
|    653  |    635  | 
|    654 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { |    636 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { | 
|    655   ASSERT(!HasFastProperties()); |    637   ASSERT(!HasFastProperties()); | 
|    656   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |    638   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 
|    657   if (IsGlobalObject()) { |    639   if (IsGlobalObject()) { | 
|    658     value = PropertyCell::cast(value)->value(); |    640     value = PropertyCell::cast(value)->value(); | 
|    659   } |    641   } | 
| (...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   1828                                Handle<Object> value, |   1810                                Handle<Object> value, | 
|   1829                                PropertyAttributes attributes, |   1811                                PropertyAttributes attributes, | 
|   1830                                StoreFromKeyed store_mode, |   1812                                StoreFromKeyed store_mode, | 
|   1831                                TransitionFlag flag) { |   1813                                TransitionFlag flag) { | 
|   1832   ASSERT(!object->IsJSGlobalProxy()); |   1814   ASSERT(!object->IsJSGlobalProxy()); | 
|   1833  |   1815  | 
|   1834   MaybeHandle<Map> maybe_map; |   1816   MaybeHandle<Map> maybe_map; | 
|   1835   if (value->IsJSFunction()) { |   1817   if (value->IsJSFunction()) { | 
|   1836     maybe_map = Map::CopyWithConstant( |   1818     maybe_map = Map::CopyWithConstant( | 
|   1837         handle(object->map()), name, value, attributes, flag); |   1819         handle(object->map()), name, value, attributes, flag); | 
|   1838   } else if (!object->TooManyFastProperties(store_mode)) { |   1820   } else if (!object->map()->TooManyFastProperties(store_mode)) { | 
|   1839     Isolate* isolate = object->GetIsolate(); |   1821     Isolate* isolate = object->GetIsolate(); | 
|   1840     Representation representation = value->OptimalRepresentation(); |   1822     Representation representation = value->OptimalRepresentation(); | 
|   1841     maybe_map = Map::CopyWithField( |   1823     maybe_map = Map::CopyWithField( | 
|   1842         handle(object->map(), isolate), name, |   1824         handle(object->map(), isolate), name, | 
|   1843         value->OptimalType(isolate, representation), |   1825         value->OptimalType(isolate, representation), | 
|   1844         attributes, representation, flag); |   1826         attributes, representation, flag); | 
|   1845   } |   1827   } | 
|   1846  |   1828  | 
|   1847   Handle<Map> new_map; |   1829   Handle<Map> new_map; | 
|   1848   if (!maybe_map.ToHandle(&new_map)) { |   1830   if (!maybe_map.ToHandle(&new_map)) { | 
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   1962   Handle<Object> args[] = { type, object, name, old_value }; |   1944   Handle<Object> args[] = { type, object, name, old_value }; | 
|   1963   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; |   1945   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; | 
|   1964  |   1946  | 
|   1965   Execution::Call(isolate, |   1947   Execution::Call(isolate, | 
|   1966                   Handle<JSFunction>(isolate->observers_notify_change()), |   1948                   Handle<JSFunction>(isolate->observers_notify_change()), | 
|   1967                   isolate->factory()->undefined_value(), |   1949                   isolate->factory()->undefined_value(), | 
|   1968                   argc, args).Assert(); |   1950                   argc, args).Assert(); | 
|   1969 } |   1951 } | 
|   1970  |   1952  | 
|   1971  |   1953  | 
|   1972 MaybeHandle<Object> JSObject::SetPropertyPostInterceptor( |  | 
|   1973     Handle<JSObject> object, |  | 
|   1974     Handle<Name> name, |  | 
|   1975     Handle<Object> value, |  | 
|   1976     StrictMode strict_mode) { |  | 
|   1977   // Check own property, ignore interceptor. |  | 
|   1978   Isolate* isolate = object->GetIsolate(); |  | 
|   1979   LookupResult result(isolate); |  | 
|   1980   object->LookupOwnRealNamedProperty(name, &result); |  | 
|   1981   if (!result.IsFound()) { |  | 
|   1982     object->map()->LookupTransition(*object, *name, &result); |  | 
|   1983   } |  | 
|   1984   return SetPropertyForResult(object, &result, name, value, strict_mode, |  | 
|   1985                               MAY_BE_STORE_FROM_KEYED); |  | 
|   1986 } |  | 
|   1987  |  | 
|   1988  |  | 
|   1989 static void ReplaceSlowProperty(Handle<JSObject> object, |   1954 static void ReplaceSlowProperty(Handle<JSObject> object, | 
|   1990                                 Handle<Name> name, |   1955                                 Handle<Name> name, | 
|   1991                                 Handle<Object> value, |   1956                                 Handle<Object> value, | 
|   1992                                 PropertyAttributes attributes) { |   1957                                 PropertyAttributes attributes) { | 
|   1993   NameDictionary* dictionary = object->property_dictionary(); |   1958   NameDictionary* dictionary = object->property_dictionary(); | 
|   1994   int old_index = dictionary->FindEntry(name); |   1959   int old_index = dictionary->FindEntry(name); | 
|   1995   int new_enumeration_index = 0;  // 0 means "Use the next available index." |   1960   int new_enumeration_index = 0;  // 0 means "Use the next available index." | 
|   1996   if (old_index != -1) { |   1961   if (old_index != -1) { | 
|   1997     // All calls to ReplaceSlowProperty have had all transitions removed. |   1962     // All calls to ReplaceSlowProperty have had all transitions removed. | 
|   1998     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |   1963     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 
| (...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   2965       case INTERCEPTOR: |   2930       case INTERCEPTOR: | 
|   2966       case NONEXISTENT: |   2931       case NONEXISTENT: | 
|   2967         UNREACHABLE(); |   2932         UNREACHABLE(); | 
|   2968     } |   2933     } | 
|   2969   } |   2934   } | 
|   2970   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); |   2935   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); | 
|   2971   return handle(new_map); |   2936   return handle(new_map); | 
|   2972 } |   2937 } | 
|   2973  |   2938  | 
|   2974  |   2939  | 
|   2975 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor( |   2940 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, | 
|   2976     Handle<JSObject> object, |   2941                                                          Handle<Object> value) { | 
|   2977     Handle<Name> name, |  | 
|   2978     Handle<Object> value, |  | 
|   2979     StrictMode strict_mode) { |  | 
|   2980   // TODO(rossberg): Support symbols in the API. |   2942   // TODO(rossberg): Support symbols in the API. | 
|   2981   if (name->IsSymbol()) return value; |   2943   if (it->name()->IsSymbol()) return value; | 
|   2982   Isolate* isolate = object->GetIsolate(); |   2944  | 
|   2983   Handle<String> name_string = Handle<String>::cast(name); |   2945   Handle<String> name_string = Handle<String>::cast(it->name()); | 
|   2984   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |   2946   Handle<JSObject> holder = it->GetHolder(); | 
|   2985   if (!interceptor->setter()->IsUndefined()) { |   2947   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); | 
|   2986     LOG(isolate, |   2948   if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>(); | 
|   2987         ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |   2949  | 
|   2988     PropertyCallbackArguments args( |   2950   LOG(it->isolate(), | 
|   2989         isolate, interceptor->data(), *object, *object); |   2951       ApiNamedPropertyAccess("interceptor-named-set", *holder, *name_string)); | 
|   2990     v8::NamedPropertySetterCallback setter = |   2952   PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder, | 
|   2991         v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |   2953                                  *holder); | 
|   2992     v8::Handle<v8::Value> result = args.Call( |   2954   v8::NamedPropertySetterCallback setter = | 
|   2993         setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value)); |   2955       v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); | 
|   2994     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |   2956   v8::Handle<v8::Value> result = args.Call( | 
|   2995     if (!result.IsEmpty()) return value; |   2957       setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value)); | 
|   2996   } |   2958   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 
|   2997   return SetPropertyPostInterceptor(object, name, value, strict_mode); |   2959   if (!result.IsEmpty()) return value; | 
 |   2960  | 
 |   2961   return MaybeHandle<Object>(); | 
|   2998 } |   2962 } | 
|   2999  |   2963  | 
|   3000  |   2964  | 
|   3001 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |   2965 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 
|   3002                                             Handle<Name> name, |   2966                                             Handle<Name> name, | 
|   3003                                             Handle<Object> value, |   2967                                             Handle<Object> value, | 
|   3004                                             StrictMode strict_mode, |   2968                                             StrictMode strict_mode, | 
|   3005                                             StoreFromKeyed store_mode) { |   2969                                             StoreFromKeyed store_mode) { | 
|   3006   LookupResult result(object->GetIsolate()); |   2970   LookupIterator it(object, name); | 
|   3007   object->LookupOwn(name, &result, true); |   2971   return Object::SetProperty(&it, value, strict_mode, store_mode); | 
|   3008   if (!result.IsFound()) { |  | 
|   3009     object->map()->LookupTransition(JSObject::cast(*object), *name, &result); |  | 
|   3010   } |  | 
|   3011   return SetProperty(object, &result, name, value, strict_mode, store_mode); |  | 
|   3012 } |   2972 } | 
|   3013  |   2973  | 
|   3014  |   2974  | 
 |   2975 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, | 
 |   2976                                         Handle<Object> value, | 
 |   2977                                         StrictMode strict_mode, | 
 |   2978                                         StoreFromKeyed store_mode) { | 
 |   2979   // Make sure that the top context does not change when doing callbacks or | 
 |   2980   // interceptor calls. | 
 |   2981   AssertNoContextChange ncc(it->isolate()); | 
 |   2982  | 
 |   2983   bool done = false; | 
 |   2984   for (; it->IsFound(); it->Next()) { | 
 |   2985     switch (it->state()) { | 
 |   2986       case LookupIterator::NOT_FOUND: | 
 |   2987         UNREACHABLE(); | 
 |   2988  | 
 |   2989       case LookupIterator::ACCESS_CHECK: | 
 |   2990         // TODO(verwaest): Remove the distinction. This is mostly bogus since we | 
 |   2991         // don't know whether we'll want to fetch attributes or call a setter | 
 |   2992         // until we find the property. | 
 |   2993         if (it->HasAccess(v8::ACCESS_SET)) break; | 
 |   2994         return JSObject::SetPropertyWithFailedAccessCheck(it, value, | 
 |   2995                                                           strict_mode); | 
 |   2996  | 
 |   2997       case LookupIterator::JSPROXY: | 
 |   2998         if (it->HolderIsReceiver()) { | 
 |   2999           return JSProxy::SetPropertyWithHandler(it->GetJSProxy(), | 
 |   3000                                                  it->GetReceiver(), it->name(), | 
 |   3001                                                  value, strict_mode); | 
 |   3002         } else { | 
 |   3003           // TODO(verwaest): Use the MaybeHandle to indicate result. | 
 |   3004           bool has_result = false; | 
 |   3005           MaybeHandle<Object> maybe_result = | 
 |   3006               JSProxy::SetPropertyViaPrototypesWithHandler( | 
 |   3007                   it->GetJSProxy(), it->GetReceiver(), it->name(), value, | 
 |   3008                   strict_mode, &has_result); | 
 |   3009           if (has_result) return maybe_result; | 
 |   3010           done = true; | 
 |   3011         } | 
 |   3012         break; | 
 |   3013  | 
 |   3014       case LookupIterator::INTERCEPTOR: | 
 |   3015         if (it->HolderIsReceiver()) { | 
 |   3016           MaybeHandle<Object> maybe_result = | 
 |   3017               JSObject::SetPropertyWithInterceptor(it, value); | 
 |   3018           if (!maybe_result.is_null()) return maybe_result; | 
 |   3019           if (it->isolate()->has_pending_exception()) return maybe_result; | 
 |   3020         } else { | 
 |   3021           Maybe<PropertyAttributes> maybe_attributes = | 
 |   3022               JSObject::GetPropertyAttributesWithInterceptor( | 
 |   3023                   it->GetHolder(), it->GetReceiver(), it->name()); | 
 |   3024           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 
 |   3025           done = maybe_attributes.has_value; | 
 |   3026           if (done && (maybe_attributes.value & READ_ONLY) != 0) { | 
 |   3027             return WriteToReadOnlyProperty(it, value, strict_mode); | 
 |   3028           } | 
 |   3029         } | 
 |   3030         break; | 
 |   3031  | 
 |   3032       case LookupIterator::PROPERTY: | 
 |   3033         if (!it->HasProperty()) break; | 
 |   3034         if (it->property_details().IsReadOnly()) { | 
 |   3035           return WriteToReadOnlyProperty(it, value, strict_mode); | 
 |   3036         } | 
 |   3037         switch (it->property_kind()) { | 
 |   3038           case LookupIterator::ACCESSOR: | 
 |   3039             if (it->HolderIsReceiver() || | 
 |   3040                 !it->GetAccessors()->IsDeclaredAccessorInfo()) { | 
 |   3041               return SetPropertyWithAccessor(it->GetReceiver(), it->name(), | 
 |   3042                                              value, it->GetHolder(), | 
 |   3043                                              it->GetAccessors(), strict_mode); | 
 |   3044             } | 
 |   3045             break; | 
 |   3046           case LookupIterator::DATA: | 
 |   3047             if (it->HolderIsReceiver()) return SetDataProperty(it, value); | 
 |   3048         } | 
 |   3049         done = true; | 
 |   3050         break; | 
 |   3051     } | 
 |   3052  | 
 |   3053     if (done) break; | 
 |   3054   } | 
 |   3055  | 
 |   3056   return AddDataProperty(it, value, NONE, strict_mode, store_mode); | 
 |   3057 } | 
 |   3058  | 
 |   3059  | 
 |   3060 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it, | 
 |   3061                                                     Handle<Object> value, | 
 |   3062                                                     StrictMode strict_mode) { | 
 |   3063   if (strict_mode != STRICT) return value; | 
 |   3064  | 
 |   3065   Handle<Object> args[] = {it->name(), it->GetReceiver()}; | 
 |   3066   Handle<Object> error = it->factory()->NewTypeError( | 
 |   3067       "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 
 |   3068   return it->isolate()->Throw<Object>(error); | 
 |   3069 } | 
 |   3070  | 
 |   3071  | 
 |   3072 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, | 
 |   3073                                             Handle<Object> value) { | 
 |   3074   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 
 |   3075   // have own properties. | 
 |   3076   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 
 |   3077  | 
 |   3078   // Store on the holder which may be hidden behind the receiver. | 
 |   3079   ASSERT(it->HolderIsReceiver()); | 
 |   3080  | 
 |   3081   // Old value for the observation change record. | 
 |   3082   // Fetch before transforming the object since the encoding may become | 
 |   3083   // incompatible with what's cached in |it|. | 
 |   3084   bool is_observed = | 
 |   3085       receiver->map()->is_observed() && | 
 |   3086       !it->name().is_identical_to(it->factory()->hidden_string()); | 
 |   3087   MaybeHandle<Object> maybe_old; | 
 |   3088   if (is_observed) maybe_old = it->GetDataValue(); | 
 |   3089  | 
 |   3090   // Possibly migrate to the most up-to-date map that will be able to store | 
 |   3091   // |value| under it->name(). | 
 |   3092   it->PrepareForDataProperty(value); | 
 |   3093  | 
 |   3094   // Write the property value. | 
 |   3095   it->WriteDataValue(value); | 
 |   3096  | 
 |   3097   // Send the change record if there are observers. | 
 |   3098   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { | 
 |   3099     JSObject::EnqueueChangeRecord(receiver, "update", it->name(), | 
 |   3100                                   maybe_old.ToHandleChecked()); | 
 |   3101   } | 
 |   3102  | 
 |   3103   return value; | 
 |   3104 } | 
 |   3105  | 
 |   3106  | 
 |   3107 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | 
 |   3108                                             Handle<Object> value, | 
 |   3109                                             PropertyAttributes attributes, | 
 |   3110                                             StrictMode strict_mode, | 
 |   3111                                             StoreFromKeyed store_mode) { | 
 |   3112   ASSERT(!it->GetReceiver()->IsJSProxy()); | 
 |   3113   // Transitions to data properties of value wrappers are not observable. | 
 |   3114   if (!it->GetReceiver()->IsJSObject()) return value; | 
 |   3115   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 
 |   3116  | 
 |   3117   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 
 |   3118   // instead. If the prototype is Null, the proxy is detached. | 
 |   3119   if (receiver->IsJSGlobalProxy()) { | 
 |   3120     // Trying to assign to a detached proxy. | 
 |   3121     PrototypeIterator iter(it->isolate(), receiver); | 
 |   3122     if (iter.IsAtEnd()) return value; | 
 |   3123     receiver = | 
 |   3124         Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); | 
 |   3125   } | 
 |   3126  | 
 |   3127   if (!receiver->map()->is_extensible()) { | 
 |   3128     if (strict_mode == SLOPPY) return value; | 
 |   3129  | 
 |   3130     Handle<Object> args[1] = {it->name()}; | 
 |   3131     Handle<Object> error = it->factory()->NewTypeError( | 
 |   3132         "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); | 
 |   3133     return it->isolate()->Throw<Object>(error); | 
 |   3134   } | 
 |   3135  | 
 |   3136   // Possibly migrate to the most up-to-date map that will be able to store | 
 |   3137   // |value| under it->name() with |attributes|. | 
 |   3138   it->TransitionToDataProperty(value, attributes, store_mode); | 
 |   3139  | 
 |   3140   // TODO(verwaest): Encapsulate dictionary handling better. | 
 |   3141   if (receiver->map()->is_dictionary_map()) { | 
 |   3142     // TODO(verwaest): Probably should ensure this is done beforehand. | 
 |   3143     it->InternalizeName(); | 
 |   3144     JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 
 |   3145   } else { | 
 |   3146     // Write the property value. | 
 |   3147     it->WriteDataValue(value); | 
 |   3148   } | 
 |   3149  | 
 |   3150   // Send the change record if there are observers. | 
 |   3151   if (receiver->map()->is_observed() && | 
 |   3152       !it->name().is_identical_to(it->factory()->hidden_string())) { | 
 |   3153     JSObject::EnqueueChangeRecord(receiver, "add", it->name(), | 
 |   3154                                   it->factory()->the_hole_value()); | 
 |   3155   } | 
 |   3156  | 
 |   3157   return value; | 
 |   3158 } | 
 |   3159  | 
 |   3160  | 
|   3015 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( |   3161 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( | 
|   3016     Handle<JSObject> object, |   3162     Handle<JSObject> object, | 
|   3017     uint32_t index, |   3163     uint32_t index, | 
|   3018     Handle<Object> value, |   3164     Handle<Object> value, | 
|   3019     bool* found, |   3165     bool* found, | 
|   3020     StrictMode strict_mode) { |   3166     StrictMode strict_mode) { | 
|   3021   Isolate *isolate = object->GetIsolate(); |   3167   Isolate *isolate = object->GetIsolate(); | 
|   3022   for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); |   3168   for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); | 
|   3023        iter.Advance()) { |   3169        iter.Advance()) { | 
|   3024     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |   3170     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   3042         return SetElementWithCallback(object, structure, index, value, js_proto, |   3188         return SetElementWithCallback(object, structure, index, value, js_proto, | 
|   3043                                       strict_mode); |   3189                                       strict_mode); | 
|   3044       } |   3190       } | 
|   3045     } |   3191     } | 
|   3046   } |   3192   } | 
|   3047   *found = false; |   3193   *found = false; | 
|   3048   return isolate->factory()->the_hole_value(); |   3194   return isolate->factory()->the_hole_value(); | 
|   3049 } |   3195 } | 
|   3050  |   3196  | 
|   3051  |   3197  | 
|   3052 MaybeHandle<Object> JSObject::SetPropertyViaPrototypes( |  | 
|   3053     Handle<JSObject> object, |  | 
|   3054     Handle<Name> name, |  | 
|   3055     Handle<Object> value, |  | 
|   3056     StrictMode strict_mode, |  | 
|   3057     bool* done) { |  | 
|   3058   Isolate* isolate = object->GetIsolate(); |  | 
|   3059  |  | 
|   3060   *done = false; |  | 
|   3061   // We could not find an own property, so let's check whether there is an |  | 
|   3062   // accessor that wants to handle the property, or whether the property is |  | 
|   3063   // read-only on the prototype chain. |  | 
|   3064   LookupResult result(isolate); |  | 
|   3065   object->LookupRealNamedPropertyInPrototypes(name, &result); |  | 
|   3066   if (result.IsFound()) { |  | 
|   3067     switch (result.type()) { |  | 
|   3068       case NORMAL: |  | 
|   3069       case FIELD: |  | 
|   3070       case CONSTANT: |  | 
|   3071         *done = result.IsReadOnly(); |  | 
|   3072         break; |  | 
|   3073       case INTERCEPTOR: { |  | 
|   3074         LookupIterator it(object, name, handle(result.holder())); |  | 
|   3075         PropertyAttributes attr = GetPropertyAttributes(&it); |  | 
|   3076         *done = !!(attr & READ_ONLY); |  | 
|   3077         break; |  | 
|   3078       } |  | 
|   3079       case CALLBACKS: { |  | 
|   3080         *done = true; |  | 
|   3081         if (!result.IsReadOnly()) { |  | 
|   3082           Handle<Object> callback_object(result.GetCallbackObject(), isolate); |  | 
|   3083           return SetPropertyWithCallback(object, name, value, |  | 
|   3084                                          handle(result.holder()), |  | 
|   3085                                          callback_object, strict_mode); |  | 
|   3086         } |  | 
|   3087         break; |  | 
|   3088       } |  | 
|   3089       case HANDLER: { |  | 
|   3090         Handle<JSProxy> proxy(result.proxy()); |  | 
|   3091         return JSProxy::SetPropertyViaPrototypesWithHandler( |  | 
|   3092             proxy, object, name, value, strict_mode, done); |  | 
|   3093       } |  | 
|   3094       case NONEXISTENT: |  | 
|   3095         UNREACHABLE(); |  | 
|   3096         break; |  | 
|   3097     } |  | 
|   3098   } |  | 
|   3099  |  | 
|   3100   // If we get here with *done true, we have encountered a read-only property. |  | 
|   3101   if (*done) { |  | 
|   3102     if (strict_mode == SLOPPY) return value; |  | 
|   3103     Handle<Object> args[] = { name, object }; |  | 
|   3104     Handle<Object> error = isolate->factory()->NewTypeError( |  | 
|   3105         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |  | 
|   3106     return isolate->Throw<Object>(error); |  | 
|   3107   } |  | 
|   3108   return isolate->factory()->the_hole_value(); |  | 
|   3109 } |  | 
|   3110  |  | 
|   3111  |  | 
|   3112 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |   3198 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 
|   3113   // Only supports adding slack to owned descriptors. |   3199   // Only supports adding slack to owned descriptors. | 
|   3114   ASSERT(map->owns_descriptors()); |   3200   ASSERT(map->owns_descriptors()); | 
|   3115  |   3201  | 
|   3116   Handle<DescriptorArray> descriptors(map->instance_descriptors()); |   3202   Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 
|   3117   int old_size = map->NumberOfOwnDescriptors(); |   3203   int old_size = map->NumberOfOwnDescriptors(); | 
|   3118   if (slack <= descriptors->NumberOfSlackDescriptors()) return; |   3204   if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 
|   3119  |   3205  | 
|   3120   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |   3206   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 
|   3121       descriptors, old_size, slack); |   3207       descriptors, old_size, slack); | 
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   3501       return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); |   3587       return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); | 
|   3502     } |   3588     } | 
|   3503     JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); |   3589     JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); | 
|   3504     ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |   3590     ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 
|   3505     if (result->IsFound()) return; |   3591     if (result->IsFound()) return; | 
|   3506   } |   3592   } | 
|   3507   result->NotFound(); |   3593   result->NotFound(); | 
|   3508 } |   3594 } | 
|   3509  |   3595  | 
|   3510  |   3596  | 
|   3511 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |  | 
|   3512                                             LookupResult* result, |  | 
|   3513                                             Handle<Name> key, |  | 
|   3514                                             Handle<Object> value, |  | 
|   3515                                             StrictMode strict_mode, |  | 
|   3516                                             StoreFromKeyed store_mode) { |  | 
|   3517   if (result->IsHandler()) { |  | 
|   3518     return JSProxy::SetPropertyWithHandler(handle(result->proxy()), object, key, |  | 
|   3519                                            value, strict_mode); |  | 
|   3520   } else { |  | 
|   3521     return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), |  | 
|   3522                                           result, key, value, strict_mode, |  | 
|   3523                                           store_mode); |  | 
|   3524   } |  | 
|   3525 } |  | 
|   3526  |  | 
|   3527  |  | 
|   3528 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { |   3597 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { | 
|   3529   Isolate* isolate = proxy->GetIsolate(); |   3598   Isolate* isolate = proxy->GetIsolate(); | 
|   3530  |   3599  | 
|   3531   // TODO(rossberg): adjust once there is a story for symbols vs proxies. |   3600   // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 
|   3532   if (name->IsSymbol()) return false; |   3601   if (name->IsSymbol()) return false; | 
|   3533  |   3602  | 
|   3534   Handle<Object> args[] = { name }; |   3603   Handle<Object> args[] = { name }; | 
|   3535   Handle<Object> result; |   3604   Handle<Object> result; | 
|   3536   ASSIGN_RETURN_ON_EXCEPTION_VALUE( |   3605   ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 
|   3537       isolate, result, |   3606       isolate, result, | 
|   3538       CallTrap(proxy, |   3607       CallTrap(proxy, | 
|   3539                "has", |   3608                "has", | 
|   3540                isolate->derived_has_trap(), |   3609                isolate->derived_has_trap(), | 
|   3541                ARRAY_SIZE(args), |   3610                ARRAY_SIZE(args), | 
|   3542                args), |   3611                args), | 
|   3543       false); |   3612       false); | 
|   3544  |   3613  | 
|   3545   return result->BooleanValue(); |   3614   return result->BooleanValue(); | 
|   3546 } |   3615 } | 
|   3547  |   3616  | 
|   3548  |   3617  | 
|   3549 MaybeHandle<Object> JSProxy::SetPropertyWithHandler( |   3618 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 
|   3550     Handle<JSProxy> proxy, |   3619                                                     Handle<Object> receiver, | 
|   3551     Handle<JSReceiver> receiver, |   3620                                                     Handle<Name> name, | 
|   3552     Handle<Name> name, |   3621                                                     Handle<Object> value, | 
|   3553     Handle<Object> value, |   3622                                                     StrictMode strict_mode) { | 
|   3554     StrictMode strict_mode) { |  | 
|   3555   Isolate* isolate = proxy->GetIsolate(); |   3623   Isolate* isolate = proxy->GetIsolate(); | 
|   3556  |   3624  | 
|   3557   // TODO(rossberg): adjust once there is a story for symbols vs proxies. |   3625   // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 
|   3558   if (name->IsSymbol()) return value; |   3626   if (name->IsSymbol()) return value; | 
|   3559  |   3627  | 
|   3560   Handle<Object> args[] = { receiver, name, value }; |   3628   Handle<Object> args[] = { receiver, name, value }; | 
|   3561   RETURN_ON_EXCEPTION( |   3629   RETURN_ON_EXCEPTION( | 
|   3562       isolate, |   3630       isolate, | 
|   3563       CallTrap(proxy, |   3631       CallTrap(proxy, | 
|   3564                "set", |   3632                "set", | 
|   3565                isolate->derived_set_trap(), |   3633                isolate->derived_set_trap(), | 
|   3566                ARRAY_SIZE(args), |   3634                ARRAY_SIZE(args), | 
|   3567                args), |   3635                args), | 
|   3568       Object); |   3636       Object); | 
|   3569  |   3637  | 
|   3570   return value; |   3638   return value; | 
|   3571 } |   3639 } | 
|   3572  |   3640  | 
|   3573  |   3641  | 
|   3574 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |   3642 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( | 
|   3575     Handle<JSProxy> proxy, |   3643     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 
|   3576     Handle<JSReceiver> receiver, |   3644     Handle<Object> value, StrictMode strict_mode, bool* done) { | 
|   3577     Handle<Name> name, |  | 
|   3578     Handle<Object> value, |  | 
|   3579     StrictMode strict_mode, |  | 
|   3580     bool* done) { |  | 
|   3581   Isolate* isolate = proxy->GetIsolate(); |   3645   Isolate* isolate = proxy->GetIsolate(); | 
|   3582   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy. |   3646   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy. | 
|   3583  |   3647  | 
|   3584   // TODO(rossberg): adjust once there is a story for symbols vs proxies. |   3648   // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 
|   3585   if (name->IsSymbol()) { |   3649   if (name->IsSymbol()) { | 
|   3586     *done = false; |   3650     *done = false; | 
|   3587     return isolate->factory()->the_hole_value(); |   3651     return isolate->factory()->the_hole_value(); | 
|   3588   } |   3652   } | 
|   3589  |   3653  | 
|   3590   *done = true;  // except where redefined... |   3654   *done = true;  // except where redefined... | 
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   3989   } |   4053   } | 
|   3990   lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value); |   4054   lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value); | 
|   3991 } |   4055 } | 
|   3992  |   4056  | 
|   3993  |   4057  | 
|   3994 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup, |   4058 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup, | 
|   3995                                         Handle<Name> name, |   4059                                         Handle<Name> name, | 
|   3996                                         Handle<Object> value, |   4060                                         Handle<Object> value, | 
|   3997                                         PropertyAttributes attributes) { |   4061                                         PropertyAttributes attributes) { | 
|   3998   Handle<JSObject> object(lookup->holder()); |   4062   Handle<JSObject> object(lookup->holder()); | 
|   3999   if (object->TooManyFastProperties()) { |   4063   if (object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) { | 
|   4000     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |   4064     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 
|   4001   } |   4065   } | 
|   4002  |   4066  | 
|   4003   if (!object->HasFastProperties()) { |   4067   if (!object->HasFastProperties()) { | 
|   4004     ReplaceSlowProperty(object, name, value, attributes); |   4068     ReplaceSlowProperty(object, name, value, attributes); | 
|   4005     return; |   4069     return; | 
|   4006   } |   4070   } | 
|   4007  |   4071  | 
|   4008   int descriptor_index = lookup->GetDescriptorIndex(); |   4072   int descriptor_index = lookup->GetDescriptorIndex(); | 
|   4009   if (lookup->GetAttributes() == attributes) { |   4073   if (lookup->GetAttributes() == attributes) { | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   4027                                                 PropertyAttributes attributes) { |   4091                                                 PropertyAttributes attributes) { | 
|   4028   if (lookup->GetAttributes() == attributes) { |   4092   if (lookup->GetAttributes() == attributes) { | 
|   4029     if (value->IsUninitialized()) return; |   4093     if (value->IsUninitialized()) return; | 
|   4030     SetPropertyToField(lookup, value); |   4094     SetPropertyToField(lookup, value); | 
|   4031   } else { |   4095   } else { | 
|   4032     ConvertAndSetOwnProperty(lookup, name, value, attributes); |   4096     ConvertAndSetOwnProperty(lookup, name, value, attributes); | 
|   4033   } |   4097   } | 
|   4034 } |   4098 } | 
|   4035  |   4099  | 
|   4036  |   4100  | 
|   4037 MaybeHandle<Object> JSObject::SetPropertyForResult( |  | 
|   4038     Handle<JSObject> object, |  | 
|   4039     LookupResult* lookup, |  | 
|   4040     Handle<Name> name, |  | 
|   4041     Handle<Object> value, |  | 
|   4042     StrictMode strict_mode, |  | 
|   4043     StoreFromKeyed store_mode) { |  | 
|   4044   ASSERT(!value->IsTheHole()); |  | 
|   4045   Isolate* isolate = object->GetIsolate(); |  | 
|   4046  |  | 
|   4047   // Make sure that the top context does not change when doing callbacks or |  | 
|   4048   // interceptor calls. |  | 
|   4049   AssertNoContextChange ncc(isolate); |  | 
|   4050  |  | 
|   4051   // Optimization for 2-byte strings often used as keys in a decompression |  | 
|   4052   // dictionary.  We internalize these short keys to avoid constantly |  | 
|   4053   // reallocating them. |  | 
|   4054   if (name->IsString() && !name->IsInternalizedString() && |  | 
|   4055       Handle<String>::cast(name)->length() <= 2) { |  | 
|   4056     name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); |  | 
|   4057   } |  | 
|   4058  |  | 
|   4059   // Check access rights if needed. |  | 
|   4060   if (object->IsAccessCheckNeeded()) { |  | 
|   4061     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |  | 
|   4062       return SetPropertyWithFailedAccessCheck(object, lookup, name, value, |  | 
|   4063                                               true, strict_mode); |  | 
|   4064     } |  | 
|   4065   } |  | 
|   4066  |  | 
|   4067   if (object->IsJSGlobalProxy()) { |  | 
|   4068     PrototypeIterator iter(isolate, object); |  | 
|   4069     if (iter.IsAtEnd()) return value; |  | 
|   4070     ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |  | 
|   4071     return SetPropertyForResult( |  | 
|   4072         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), lookup, |  | 
|   4073         name, value, strict_mode, store_mode); |  | 
|   4074   } |  | 
|   4075  |  | 
|   4076   ASSERT(!lookup->IsFound() || lookup->holder() == *object || |  | 
|   4077          lookup->holder()->map()->is_hidden_prototype()); |  | 
|   4078  |  | 
|   4079   if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) { |  | 
|   4080     bool done = false; |  | 
|   4081     Handle<Object> result_object; |  | 
|   4082     ASSIGN_RETURN_ON_EXCEPTION( |  | 
|   4083         isolate, result_object, |  | 
|   4084         SetPropertyViaPrototypes(object, name, value, strict_mode, &done), |  | 
|   4085         Object); |  | 
|   4086     if (done) return result_object; |  | 
|   4087   } |  | 
|   4088  |  | 
|   4089   if (!lookup->IsFound()) { |  | 
|   4090     // Neither properties nor transitions found. |  | 
|   4091     return AddPropertyInternal(object, name, value, NONE, strict_mode, |  | 
|   4092                                store_mode); |  | 
|   4093   } |  | 
|   4094  |  | 
|   4095   if (lookup->IsProperty() && lookup->IsReadOnly()) { |  | 
|   4096     if (strict_mode == STRICT) { |  | 
|   4097       Handle<Object> args[] = { name, object }; |  | 
|   4098       Handle<Object> error = isolate->factory()->NewTypeError( |  | 
|   4099           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |  | 
|   4100       return isolate->Throw<Object>(error); |  | 
|   4101     } else { |  | 
|   4102       return value; |  | 
|   4103     } |  | 
|   4104   } |  | 
|   4105  |  | 
|   4106   Handle<Object> old_value = isolate->factory()->the_hole_value(); |  | 
|   4107   bool is_observed = object->map()->is_observed() && |  | 
|   4108                      *name != isolate->heap()->hidden_string(); |  | 
|   4109   if (is_observed && lookup->IsDataProperty()) { |  | 
|   4110     old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked(); |  | 
|   4111   } |  | 
|   4112  |  | 
|   4113   // This is a real property that is not read-only, or it is a |  | 
|   4114   // transition or null descriptor and there are no setters in the prototypes. |  | 
|   4115   MaybeHandle<Object> maybe_result = value; |  | 
|   4116   if (lookup->IsTransition()) { |  | 
|   4117     maybe_result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, |  | 
|   4118                                               name, value, NONE); |  | 
|   4119   } else { |  | 
|   4120     switch (lookup->type()) { |  | 
|   4121       case NORMAL: |  | 
|   4122         SetNormalizedProperty(handle(lookup->holder()), lookup, value); |  | 
|   4123         break; |  | 
|   4124       case FIELD: |  | 
|   4125         SetPropertyToField(lookup, value); |  | 
|   4126         break; |  | 
|   4127       case CONSTANT: |  | 
|   4128         // Only replace the constant if necessary. |  | 
|   4129         if (*value == lookup->GetConstant()) return value; |  | 
|   4130         SetPropertyToField(lookup, value); |  | 
|   4131         break; |  | 
|   4132       case CALLBACKS: { |  | 
|   4133         Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); |  | 
|   4134         return SetPropertyWithCallback(object, name, value, |  | 
|   4135                                        handle(lookup->holder()), |  | 
|   4136                                        callback_object, strict_mode); |  | 
|   4137       } |  | 
|   4138       case INTERCEPTOR: |  | 
|   4139         maybe_result = SetPropertyWithInterceptor(handle(lookup->holder()), |  | 
|   4140                                                   name, value, strict_mode); |  | 
|   4141         break; |  | 
|   4142       case HANDLER: |  | 
|   4143       case NONEXISTENT: |  | 
|   4144         UNREACHABLE(); |  | 
|   4145     } |  | 
|   4146   } |  | 
|   4147  |  | 
|   4148   Handle<Object> result; |  | 
|   4149   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object); |  | 
|   4150  |  | 
|   4151   if (is_observed) { |  | 
|   4152     if (lookup->IsTransition()) { |  | 
|   4153       EnqueueChangeRecord(object, "add", name, old_value); |  | 
|   4154     } else { |  | 
|   4155       LookupResult new_lookup(isolate); |  | 
|   4156       object->LookupOwn(name, &new_lookup, true); |  | 
|   4157       if (new_lookup.IsDataProperty()) { |  | 
|   4158         Handle<Object> new_value = |  | 
|   4159             Object::GetPropertyOrElement(object, name).ToHandleChecked(); |  | 
|   4160         if (!new_value->SameValue(*old_value)) { |  | 
|   4161           EnqueueChangeRecord(object, "update", name, old_value); |  | 
|   4162         } |  | 
|   4163       } |  | 
|   4164     } |  | 
|   4165   } |  | 
|   4166  |  | 
|   4167   return result; |  | 
|   4168 } |  | 
|   4169  |  | 
|   4170  |  | 
|   4171 void JSObject::AddProperty( |   4101 void JSObject::AddProperty( | 
|   4172     Handle<JSObject> object, |   4102     Handle<JSObject> object, | 
|   4173     Handle<Name> name, |   4103     Handle<Name> name, | 
|   4174     Handle<Object> value, |   4104     Handle<Object> value, | 
|   4175     PropertyAttributes attributes, |   4105     PropertyAttributes attributes, | 
|   4176     StoreMode store_mode) { |   4106     StoreMode store_mode) { | 
|   4177 #ifdef DEBUG |   4107 #ifdef DEBUG | 
|   4178   uint32_t index; |   4108   uint32_t index; | 
|   4179   ASSERT(!object->IsJSProxy()); |   4109   ASSERT(!object->IsJSProxy()); | 
|   4180   ASSERT(!name->AsArrayIndex(&index)); |   4110   ASSERT(!name->AsArrayIndex(&index)); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   4208  |   4138  | 
|   4209   LookupResult lookup(isolate); |   4139   LookupResult lookup(isolate); | 
|   4210   object->LookupOwn(name, &lookup, true); |   4140   object->LookupOwn(name, &lookup, true); | 
|   4211   if (!lookup.IsFound()) { |   4141   if (!lookup.IsFound()) { | 
|   4212     object->map()->LookupTransition(*object, *name, &lookup); |   4142     object->map()->LookupTransition(*object, *name, &lookup); | 
|   4213   } |   4143   } | 
|   4214  |   4144  | 
|   4215   // Check access rights if needed. |   4145   // Check access rights if needed. | 
|   4216   if (object->IsAccessCheckNeeded()) { |   4146   if (object->IsAccessCheckNeeded()) { | 
|   4217     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |   4147     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 
|   4218       return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, |   4148       LookupIterator it(object, name, LookupIterator::CHECK_OWN); | 
|   4219                                               false, SLOPPY); |   4149       return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); | 
|   4220     } |   4150     } | 
|   4221   } |   4151   } | 
|   4222  |   4152  | 
|   4223   if (object->IsJSGlobalProxy()) { |   4153   if (object->IsJSGlobalProxy()) { | 
|   4224     PrototypeIterator iter(isolate, object); |   4154     PrototypeIterator iter(isolate, object); | 
|   4225     if (iter.IsAtEnd()) return value; |   4155     if (iter.IsAtEnd()) return value; | 
|   4226     ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |   4156     ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 
|   4227     return SetOwnPropertyIgnoreAttributes( |   4157     return SetOwnPropertyIgnoreAttributes( | 
|   4228         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, |   4158         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, | 
|   4229         value, attributes, mode, extensibility_check); |   4159         value, attributes, mode, extensibility_check); | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   4281           SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |   4211           SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); | 
|   4282         } |   4212         } | 
|   4283         break; |   4213         break; | 
|   4284       case CALLBACKS: |   4214       case CALLBACKS: | 
|   4285       { |   4215       { | 
|   4286         Handle<Object> callback(lookup.GetCallbackObject(), isolate); |   4216         Handle<Object> callback(lookup.GetCallbackObject(), isolate); | 
|   4287         if (callback->IsExecutableAccessorInfo() && |   4217         if (callback->IsExecutableAccessorInfo() && | 
|   4288             handling == DONT_FORCE_FIELD) { |   4218             handling == DONT_FORCE_FIELD) { | 
|   4289           Handle<Object> result; |   4219           Handle<Object> result; | 
|   4290           ASSIGN_RETURN_ON_EXCEPTION( |   4220           ASSIGN_RETURN_ON_EXCEPTION( | 
|   4291               isolate, result, |   4221               isolate, result, JSObject::SetPropertyWithAccessor( | 
|   4292               JSObject::SetPropertyWithCallback(object, |   4222                                    object, name, value, handle(lookup.holder()), | 
|   4293                                                 name, |   4223                                    callback, STRICT), | 
|   4294                                                 value, |  | 
|   4295                                                 handle(lookup.holder()), |  | 
|   4296                                                 callback, |  | 
|   4297                                                 STRICT), |  | 
|   4298               Object); |   4224               Object); | 
|   4299  |   4225  | 
|   4300           if (attributes != lookup.GetAttributes()) { |   4226           if (attributes != lookup.GetAttributes()) { | 
|   4301             Handle<ExecutableAccessorInfo> new_data = |   4227             Handle<ExecutableAccessorInfo> new_data = | 
|   4302                 Accessors::CloneAccessor( |   4228                 Accessors::CloneAccessor( | 
|   4303                     isolate, Handle<ExecutableAccessorInfo>::cast(callback)); |   4229                     isolate, Handle<ExecutableAccessorInfo>::cast(callback)); | 
|   4304             new_data->set_property_attributes(attributes); |   4230             new_data->set_property_attributes(attributes); | 
|   4305             if (attributes & READ_ONLY) { |   4231             if (attributes & READ_ONLY) { | 
|   4306               // This way we don't have to introduce a lookup to the setter, |   4232               // This way we don't have to introduce a lookup to the setter, | 
|   4307               // simply make it unavailable to reflect the attributes. |   4233               // simply make it unavailable to reflect the attributes. | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   4356  |   4282  | 
|   4357   return value; |   4283   return value; | 
|   4358 } |   4284 } | 
|   4359  |   4285  | 
|   4360  |   4286  | 
|   4361 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( |   4287 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( | 
|   4362     Handle<JSObject> holder, |   4288     Handle<JSObject> holder, | 
|   4363     Handle<Object> receiver, |   4289     Handle<Object> receiver, | 
|   4364     Handle<Name> name) { |   4290     Handle<Name> name) { | 
|   4365   // TODO(rossberg): Support symbols in the API. |   4291   // TODO(rossberg): Support symbols in the API. | 
|   4366   if (name->IsSymbol()) return Maybe<PropertyAttributes>(ABSENT); |   4292   if (name->IsSymbol()) return Maybe<PropertyAttributes>(); | 
|   4367  |   4293  | 
|   4368   Isolate* isolate = holder->GetIsolate(); |   4294   Isolate* isolate = holder->GetIsolate(); | 
|   4369   HandleScope scope(isolate); |   4295   HandleScope scope(isolate); | 
|   4370  |   4296  | 
|   4371   // Make sure that the top context does not change when doing |   4297   // Make sure that the top context does not change when doing | 
|   4372   // callbacks or interceptor calls. |   4298   // callbacks or interceptor calls. | 
|   4373   AssertNoContextChange ncc(isolate); |   4299   AssertNoContextChange ncc(isolate); | 
|   4374  |   4300  | 
|   4375   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); |   4301   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); | 
|   4376   PropertyCallbackArguments args( |   4302   PropertyCallbackArguments args( | 
| (...skipping 2983 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   7360       handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); |   7286       handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); | 
|   7361   Handle<Map> new_map = CopyReplaceDescriptors( |   7287   Handle<Map> new_map = CopyReplaceDescriptors( | 
|   7362       map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol()); |   7288       map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol()); | 
|   7363   new_map->freeze(); |   7289   new_map->freeze(); | 
|   7364   new_map->set_is_extensible(false); |   7290   new_map->set_is_extensible(false); | 
|   7365   new_map->set_elements_kind(DICTIONARY_ELEMENTS); |   7291   new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 
|   7366   return new_map; |   7292   return new_map; | 
|   7367 } |   7293 } | 
|   7368  |   7294  | 
|   7369  |   7295  | 
 |   7296 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { | 
 |   7297   PropertyDetails details = GetDetails(descriptor); | 
 |   7298   switch (details.type()) { | 
 |   7299     case FIELD: | 
 |   7300       return value->FitsRepresentation(details.representation()) && | 
 |   7301              GetFieldType(descriptor)->NowContains(value); | 
 |   7302  | 
 |   7303     case CONSTANT: | 
 |   7304       ASSERT(GetConstant(descriptor) != value || | 
 |   7305              value->FitsRepresentation(details.representation())); | 
 |   7306       return GetConstant(descriptor) == value; | 
 |   7307  | 
 |   7308     case CALLBACKS: | 
 |   7309       return false; | 
 |   7310  | 
 |   7311     case NORMAL: | 
 |   7312     case INTERCEPTOR: | 
 |   7313     case HANDLER: | 
 |   7314     case NONEXISTENT: | 
 |   7315       break; | 
 |   7316   } | 
 |   7317  | 
 |   7318   UNREACHABLE(); | 
 |   7319   return false; | 
 |   7320 } | 
 |   7321  | 
 |   7322  | 
 |   7323 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, | 
 |   7324                                         Handle<Object> value) { | 
 |   7325   // Dictionaries can store any property value. | 
 |   7326   if (map->is_dictionary_map()) return map; | 
 |   7327  | 
 |   7328   Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 
 |   7329  | 
 |   7330   if (descriptors->CanHoldValue(descriptor, *value)) return map; | 
 |   7331  | 
 |   7332   Isolate* isolate = map->GetIsolate(); | 
 |   7333   Representation representation = value->OptimalRepresentation(); | 
 |   7334   Handle<HeapType> type = value->OptimalType(isolate, representation); | 
 |   7335  | 
 |   7336   return GeneralizeRepresentation(map, descriptor, representation, type, | 
 |   7337                                   FORCE_FIELD); | 
 |   7338 } | 
 |   7339  | 
 |   7340  | 
 |   7341 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 
 |   7342                                           Handle<Object> value, | 
 |   7343                                           PropertyAttributes attributes, | 
 |   7344                                           StoreFromKeyed store_mode) { | 
 |   7345   // Cannot currently handle deprecated maps. | 
 |   7346   ASSERT(!map->is_deprecated()); | 
 |   7347   // Dictionary maps can always have additional data properties. | 
 |   7348   if (map->is_dictionary_map()) return map; | 
 |   7349  | 
 |   7350   int index = map->SearchTransition(*name); | 
 |   7351   if (index != TransitionArray::kNotFound) { | 
 |   7352     Handle<Map> transition(map->GetTransition(index)); | 
 |   7353     int descriptor = transition->LastAdded(); | 
 |   7354  | 
 |   7355     // TODO(verwaest): Handle attributes better. | 
 |   7356     DescriptorArray* descriptors = transition->instance_descriptors(); | 
 |   7357     if (descriptors->GetDetails(descriptor).attributes() != attributes) { | 
 |   7358       return CopyGeneralizeAllRepresentations(transition, descriptor, | 
 |   7359                                               FORCE_FIELD, attributes, | 
 |   7360                                               "attributes mismatch"); | 
 |   7361     } | 
 |   7362  | 
 |   7363     return Map::PrepareForDataProperty(transition, descriptor, value); | 
 |   7364   } | 
 |   7365  | 
 |   7366   TransitionFlag flag = INSERT_TRANSITION; | 
 |   7367   MaybeHandle<Map> maybe_map; | 
 |   7368   if (value->IsJSFunction()) { | 
 |   7369     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); | 
 |   7370   } else if (!map->TooManyFastProperties(store_mode)) { | 
 |   7371     Isolate* isolate = name->GetIsolate(); | 
 |   7372     Representation representation = value->OptimalRepresentation(); | 
 |   7373     Handle<HeapType> type = value->OptimalType(isolate, representation); | 
 |   7374     maybe_map = | 
 |   7375         Map::CopyWithField(map, name, type, attributes, representation, flag); | 
 |   7376   } | 
 |   7377  | 
 |   7378   Handle<Map> result; | 
 |   7379   if (!maybe_map.ToHandle(&result)) { | 
 |   7380     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); | 
 |   7381   } | 
 |   7382  | 
 |   7383   return result; | 
 |   7384 } | 
 |   7385  | 
 |   7386  | 
|   7370 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |   7387 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, | 
|   7371                                    Descriptor* descriptor, |   7388                                    Descriptor* descriptor, | 
|   7372                                    TransitionFlag flag) { |   7389                                    TransitionFlag flag) { | 
|   7373   Handle<DescriptorArray> descriptors(map->instance_descriptors()); |   7390   Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 
|   7374  |   7391  | 
|   7375   // Ensure the key is unique. |   7392   // Ensure the key is unique. | 
|   7376   descriptor->KeyToUniqueName(); |   7393   descriptor->KeyToUniqueName(); | 
|   7377  |   7394  | 
|   7378   if (flag == INSERT_TRANSITION && |   7395   if (flag == INSERT_TRANSITION && | 
|   7379       map->owns_descriptors() && |   7396       map->owns_descriptors() && | 
| (...skipping 9530 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  16910 #define ERROR_MESSAGES_TEXTS(C, T) T, |  16927 #define ERROR_MESSAGES_TEXTS(C, T) T, | 
|  16911   static const char* error_messages_[] = { |  16928   static const char* error_messages_[] = { | 
|  16912       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |  16929       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 
|  16913   }; |  16930   }; | 
|  16914 #undef ERROR_MESSAGES_TEXTS |  16931 #undef ERROR_MESSAGES_TEXTS | 
|  16915   return error_messages_[reason]; |  16932   return error_messages_[reason]; | 
|  16916 } |  16933 } | 
|  16917  |  16934  | 
|  16918  |  16935  | 
|  16919 } }  // namespace v8::internal |  16936 } }  // namespace v8::internal | 
| OLD | NEW |