| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 57483177854d3928d838967bf9c8a98adc7f6a54..d3fb3139cd3b38c5f6b1b7382632eac470a26648 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -2830,8 +2830,8 @@ MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
|
|
|
|
|
| MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
|
| - String* name,
|
| - Object* value,
|
| + String* name_raw,
|
| + Object* value_raw,
|
| PropertyAttributes attributes,
|
| StrictModeFlag strict_mode,
|
| StoreFromKeyed store_mode) {
|
| @@ -2843,113 +2843,123 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
|
| // Optimization for 2-byte strings often used as keys in a decompression
|
| // dictionary. We make these short keys into symbols to avoid constantly
|
| // reallocating them.
|
| - if (!name->IsSymbol() && name->length() <= 2) {
|
| + if (!name_raw->IsSymbol() && name_raw->length() <= 2) {
|
| Object* symbol_version;
|
| - { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
|
| + { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw);
|
| if (maybe_symbol_version->ToObject(&symbol_version)) {
|
| - name = String::cast(symbol_version);
|
| + name_raw = String::cast(symbol_version);
|
| }
|
| }
|
| }
|
|
|
| // Check access rights if needed.
|
| if (IsAccessCheckNeeded()) {
|
| - if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
|
| + if (!heap->isolate()->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
|
| return SetPropertyWithFailedAccessCheck(
|
| - result, name, value, true, strict_mode);
|
| + result, name_raw, value_raw, true, strict_mode);
|
| }
|
| }
|
|
|
| if (IsJSGlobalProxy()) {
|
| Object* proto = GetPrototype();
|
| - if (proto->IsNull()) return value;
|
| + if (proto->IsNull()) return value_raw;
|
| ASSERT(proto->IsJSGlobalObject());
|
| return JSObject::cast(proto)->SetPropertyForResult(
|
| - result, name, value, attributes, strict_mode, store_mode);
|
| + result, name_raw, value_raw, attributes, strict_mode, store_mode);
|
| }
|
|
|
| - if (!result->IsProperty() && !IsJSContextExtensionObject()) {
|
| + // From this point on everything needs to be handlified, because
|
| + // SetPropertyViaPrototypes might call back into JavaScript.
|
| + Handle<JSObject> self(this);
|
| + Handle<String> name(name_raw);
|
| + Handle<Object> value(value_raw);
|
| +
|
| + if (!result->IsProperty() && !self->IsJSContextExtensionObject()) {
|
| bool done = false;
|
| - MaybeObject* result_object =
|
| - SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
|
| + MaybeObject* result_object = self->SetPropertyViaPrototypes(
|
| + *name, *value, attributes, strict_mode, &done);
|
| if (done) return result_object;
|
| }
|
|
|
| if (!result->IsFound()) {
|
| // Neither properties nor transitions found.
|
| - return AddProperty(name, value, attributes, strict_mode, store_mode);
|
| + return self->AddProperty(
|
| + *name, *value, attributes, strict_mode, store_mode);
|
| }
|
| if (result->IsReadOnly() && result->IsProperty()) {
|
| if (strict_mode == kStrictMode) {
|
| - Handle<JSObject> self(this);
|
| - Handle<String> hname(name);
|
| - Handle<Object> args[] = { hname, self };
|
| + Handle<Object> args[] = { name, self };
|
| return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
|
| "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
|
| } else {
|
| - return value;
|
| + return *value;
|
| }
|
| }
|
| // This is a real property that is not read-only, or it is a
|
| // transition or null descriptor and there are no setters in the prototypes.
|
| switch (result->type()) {
|
| case NORMAL:
|
| - return SetNormalizedProperty(result, value);
|
| + return self->SetNormalizedProperty(result, *value);
|
| case FIELD:
|
| - return FastPropertyAtPut(result->GetFieldIndex(), value);
|
| + return self->FastPropertyAtPut(result->GetFieldIndex(), *value);
|
| case MAP_TRANSITION:
|
| if (attributes == result->GetAttributes()) {
|
| // Only use map transition if the attributes match.
|
| - return AddFastPropertyUsingMap(result->GetTransitionMap(),
|
| - name,
|
| - value);
|
| + return self->AddFastPropertyUsingMap(result->GetTransitionMap(),
|
| + *name,
|
| + *value);
|
| }
|
| - return ConvertDescriptorToField(name, value, attributes);
|
| + return self->ConvertDescriptorToField(*name, *value, attributes);
|
| case CONSTANT_FUNCTION:
|
| // Only replace the function if necessary.
|
| - if (value == result->GetConstantFunction()) return value;
|
| + if (*value == result->GetConstantFunction()) return *value;
|
| // Preserve the attributes of this existing property.
|
| attributes = result->GetAttributes();
|
| - return ConvertDescriptorToField(name, value, attributes);
|
| + return self->ConvertDescriptorToField(*name, *value, attributes);
|
| case CALLBACKS: {
|
| Object* callback_object = result->GetCallbackObject();
|
| if (callback_object->IsAccessorPair() &&
|
| !AccessorPair::cast(callback_object)->ContainsAccessor()) {
|
| - return ConvertDescriptorToField(name, value, attributes);
|
| + return self->ConvertDescriptorToField(*name, *value, attributes);
|
| }
|
| - return SetPropertyWithCallback(callback_object,
|
| - name,
|
| - value,
|
| - result->holder(),
|
| - strict_mode);
|
| + return self->SetPropertyWithCallback(callback_object,
|
| + *name,
|
| + *value,
|
| + result->holder(),
|
| + strict_mode);
|
| }
|
| case INTERCEPTOR:
|
| - return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
|
| + return self->SetPropertyWithInterceptor(*name,
|
| + *value,
|
| + attributes,
|
| + strict_mode);
|
| case CONSTANT_TRANSITION: {
|
| // If the same constant function is being added we can simply
|
| // transition to the target map.
|
| Map* target_map = result->GetTransitionMap();
|
| DescriptorArray* target_descriptors = target_map->instance_descriptors();
|
| - int number = target_descriptors->SearchWithCache(name);
|
| + int number = target_descriptors->SearchWithCache(*name);
|
| ASSERT(number != DescriptorArray::kNotFound);
|
| ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
|
| JSFunction* function =
|
| JSFunction::cast(target_descriptors->GetValue(number));
|
| - if (value == function) {
|
| - set_map(target_map);
|
| - return value;
|
| + if (*value == function) {
|
| + self->set_map(target_map);
|
| + return *value;
|
| }
|
| // Otherwise, replace with a MAP_TRANSITION to a new map with a
|
| // FIELD, even if the value is a constant function.
|
| - return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
|
| + return self->ConvertDescriptorToFieldAndMapTransition(*name,
|
| + *value,
|
| + attributes);
|
| }
|
| case HANDLER:
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| - return value;
|
| + return *value;
|
| }
|
| UNREACHABLE(); // keep the compiler happy
|
| - return value;
|
| + return *value;
|
| }
|
|
|
|
|
|
|