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; |
} |