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

Unified Diff: src/objects.cc

Issue 10534090: Rollback of r11719, r11717, r11716, r11714, r11700, r11699, r11697, r11695, r11694 in trunk branch. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 6 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/stub-cache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index e5f0e494558ffa70212308523de5c595448b3121..49ab9707197397aab2b5aea09ad205cf8ef81924 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1762,11 +1762,14 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
// found. Use set property to handle all these cases.
return SetProperty(&result, name, value, attributes, strict_mode);
}
- bool done = false;
+ bool found = false;
MaybeObject* result_object;
- result_object =
- SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
- if (done) return result_object;
+ result_object = SetPropertyWithCallbackSetterInPrototypes(name,
+ value,
+ attributes,
+ &found,
+ strict_mode);
+ if (found) return result_object;
// Add a new real property.
return AddProperty(name, value, attributes, strict_mode);
}
@@ -2046,6 +2049,26 @@ MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
}
+void JSObject::LookupCallbackSetterInPrototypes(String* name,
+ LookupResult* result) {
+ Heap* heap = GetHeap();
+ for (Object* pt = GetPrototype();
+ pt != heap->null_value();
+ pt = pt->GetPrototype()) {
+ if (pt->IsJSProxy()) {
+ return result->HandlerResult(JSProxy::cast(pt));
+ }
+ JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
+ if (result->IsProperty()) {
+ if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
+ // Found non-callback or read-only callback, stop looking.
+ break;
+ }
+ }
+ result->NotFound();
+}
+
+
MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
uint32_t index,
Object* value,
@@ -2062,7 +2085,7 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
*found = true; // Force abort
return maybe;
}
- return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler(
+ return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
this, name, value, NONE, strict_mode, found);
}
if (!JSObject::cast(pt)->HasDictionaryElements()) {
@@ -2087,61 +2110,45 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
return heap->the_hole_value();
}
-MaybeObject* JSObject::SetPropertyViaPrototypes(
+MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
String* name,
Object* value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
- bool* done) {
+ bool* found,
+ StrictModeFlag strict_mode) {
Heap* heap = GetHeap();
- Isolate* isolate = heap->isolate();
-
- *done = false;
// We could not find a local property so let's check whether there is an
- // accessor that wants to handle the property, or whether the property is
- // read-only on the prototype chain.
- LookupResult result(isolate);
- LookupRealNamedPropertyInPrototypes(name, &result);
- if (result.IsFound()) {
- switch (result.type()) {
- case NORMAL:
- case FIELD:
- case CONSTANT_FUNCTION:
- *done = result.IsReadOnly();
- break;
- case INTERCEPTOR: {
- PropertyAttributes attr =
- result.holder()->GetPropertyAttributeWithInterceptor(
- this, name, true);
- *done = !!(attr & READ_ONLY);
- break;
- }
- case CALLBACKS: {
- if (!FLAG_es5_readonly && result.IsReadOnly()) break;
- *done = true;
- return SetPropertyWithCallback(result.GetCallbackObject(),
- name, value, result.holder(), strict_mode);
- }
- case HANDLER: {
- return result.proxy()->SetPropertyViaPrototypesWithHandler(
- this, name, value, attributes, strict_mode, done);
- }
- case MAP_TRANSITION:
- case CONSTANT_TRANSITION:
- case NULL_DESCRIPTOR:
- case ELEMENTS_TRANSITION:
- break;
+ // accessor that wants to handle the property.
+ LookupResult accessor_result(heap->isolate());
+ LookupCallbackSetterInPrototypes(name, &accessor_result);
+ if (accessor_result.IsFound()) {
+ *found = true;
+ if (accessor_result.type() == CALLBACKS) {
+ return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
+ name,
+ value,
+ accessor_result.holder(),
+ strict_mode);
+ } else if (accessor_result.type() == HANDLER) {
+ // There is a proxy in the prototype chain. Invoke its
+ // getPropertyDescriptor trap.
+ bool found = false;
+ // SetPropertyWithHandlerIfDefiningSetter can cause GC,
+ // make sure to use the handlified references after calling
+ // the function.
+ Handle<JSObject> self(this);
+ Handle<String> hname(name);
+ Handle<Object> hvalue(value);
+ MaybeObject* result =
+ accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
+ this, name, value, attributes, strict_mode, &found);
+ if (found) return result;
+ // The proxy does not define the property as an accessor.
+ // Consequently, it has no effect on setting the receiver.
+ return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
}
}
-
- // If we get here with *done true, we have encountered a read-only property.
- if (!FLAG_es5_readonly) *done = false;
- if (*done) {
- if (strict_mode == kNonStrictMode) return value;
- Handle<Object> args[] = { Handle<Object>(name), Handle<Object>(this)};
- return isolate->Throw(*isolate->factory()->NewTypeError(
- "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
- }
+ *found = false;
return heap->the_hole_value();
}
@@ -2546,13 +2553,9 @@ void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
Heap* heap = GetHeap();
for (Object* pt = GetPrototype();
pt != heap->null_value();
- pt = pt->GetPrototype()) {
- if (pt->IsJSProxy()) {
- return result->HandlerResult(JSProxy::cast(pt));
- }
+ pt = JSObject::cast(pt)->GetPrototype()) {
JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
- ASSERT(!(result->IsProperty() && result->type() == INTERCEPTOR));
- if (result->IsProperty()) return;
+ if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
}
result->NotFound();
}
@@ -2566,7 +2569,7 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
bool check_prototype,
StrictModeFlag strict_mode) {
if (check_prototype && !result->IsProperty()) {
- LookupRealNamedPropertyInPrototypes(name, result);
+ LookupCallbackSetterInPrototypes(name, result);
}
if (result->IsProperty()) {
@@ -2639,7 +2642,7 @@ bool JSProxy::HasPropertyWithHandler(String* name_raw) {
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
- if (isolate->has_pending_exception()) return false;
+ if (isolate->has_pending_exception()) return Failure::Exception();
return result->ToBoolean()->IsTrue();
}
@@ -2665,92 +2668,79 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
}
-MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
+MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
JSReceiver* receiver_raw,
String* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
- bool* done) {
- Isolate* isolate = GetIsolate();
- Handle<JSProxy> proxy(this);
+ bool* found) {
+ *found = true; // except where defined otherwise...
+ Isolate* isolate = GetHeap()->isolate();
Handle<JSReceiver> receiver(receiver_raw);
+ Handle<JSProxy> proxy(this);
+ Handle<Object> handler(this->handler()); // Trap might morph proxy.
Handle<String> name(name_raw);
Handle<Object> value(value_raw);
- Handle<Object> handler(this->handler()); // Trap might morph proxy.
-
- *done = true; // except where redefined...
Handle<Object> args[] = { name };
Handle<Object> result = proxy->CallTrap(
"getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
if (isolate->has_pending_exception()) return Failure::Exception();
- if (result->IsUndefined()) {
- *done = false;
- return GetHeap()->the_hole_value();
- }
-
- // Emulate [[GetProperty]] semantics for proxies.
- bool has_pending_exception;
- Handle<Object> argv[] = { result };
- Handle<Object> desc =
- Execution::Call(isolate->to_complete_property_descriptor(), result,
- ARRAY_SIZE(argv), argv, &has_pending_exception);
- if (has_pending_exception) return Failure::Exception();
-
- // [[GetProperty]] requires to check that all properties are configurable.
- Handle<String> configurable_name =
- isolate->factory()->LookupAsciiSymbol("configurable_");
- Handle<Object> configurable(
- v8::internal::GetProperty(desc, configurable_name));
- ASSERT(!isolate->has_pending_exception());
- ASSERT(configurable->IsTrue() || configurable->IsFalse());
- if (configurable->IsFalse()) {
- Handle<String> trap =
- isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
- Handle<Object> args[] = { handler, trap, name };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
- return isolate->Throw(*error);
- }
- ASSERT(configurable->IsTrue());
-
- // Check for DataDescriptor.
- Handle<String> hasWritable_name =
- isolate->factory()->LookupAsciiSymbol("hasWritable_");
- Handle<Object> hasWritable(v8::internal::GetProperty(desc, hasWritable_name));
- ASSERT(!isolate->has_pending_exception());
- ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
- if (hasWritable->IsTrue()) {
- Handle<String> writable_name =
- isolate->factory()->LookupAsciiSymbol("writable_");
- Handle<Object> writable(v8::internal::GetProperty(desc, writable_name));
+ if (!result->IsUndefined()) {
+ // The proxy handler cares about this property.
+ // Check whether it is virtualized as an accessor.
+ // Emulate [[GetProperty]] semantics for proxies.
+ bool has_pending_exception;
+ Handle<Object> argv[] = { result };
+ Handle<Object> desc =
+ Execution::Call(isolate->to_complete_property_descriptor(), result,
+ ARRAY_SIZE(argv), argv, &has_pending_exception);
+ if (has_pending_exception) return Failure::Exception();
+
+ Handle<String> conf_name =
+ isolate->factory()->LookupAsciiSymbol("configurable_");
+ Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
ASSERT(!isolate->has_pending_exception());
- ASSERT(writable->IsTrue() || writable->IsFalse());
- *done = writable->IsFalse();
- if (!*done) return GetHeap()->the_hole_value();
- if (strict_mode == kNonStrictMode) return *value;
- Handle<Object> args[] = { name, receiver };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
- return isolate->Throw(*error);
- }
+ if (configurable->IsFalse()) {
+ Handle<String> trap =
+ isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
+ Handle<Object> args[] = { handler, trap, name };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
+ return isolate->Throw(*error);
+ }
+ ASSERT(configurable->IsTrue());
- // We have an AccessorDescriptor.
- Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
- Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
- ASSERT(!isolate->has_pending_exception());
- if (!setter->IsUndefined()) {
- // TODO(rossberg): nicer would be to cast to some JSCallable here...
- return receiver->SetPropertyWithDefinedSetter(
- JSReceiver::cast(*setter), *value);
+ // Check for AccessorDescriptor.
+ Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
+ Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
+ ASSERT(!isolate->has_pending_exception());
+ if (!setter->IsUndefined()) {
+ // We have a setter -- invoke it.
+ // TODO(rossberg): nicer would be to cast to some JSCallable here...
+ return receiver->SetPropertyWithDefinedSetter(
+ JSReceiver::cast(*setter), *value);
+ } else {
+ Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
+ Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
+ ASSERT(!isolate->has_pending_exception());
+ if (!getter->IsUndefined()) {
+ // We have a getter but no setter -- the property may not be
+ // written. In strict mode, throw an error.
+ if (strict_mode == kNonStrictMode) return *value;
+ Handle<Object> args[] = { name, proxy };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
+ return isolate->Throw(*error);
+ }
+ }
+ // Fall-through.
}
- if (strict_mode == kNonStrictMode) return *value;
- Handle<Object> args2[] = { name, proxy };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
- return isolate->Throw(*error);
+ // The proxy does not define the property as an accessor.
+ *found = false;
+ return *value;
}
@@ -2943,11 +2933,18 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
}
if (!result->IsProperty() && !IsJSContextExtensionObject()) {
- bool done = false;
- MaybeObject* result_object =
- SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
- if (done) return result_object;
- }
+ bool found = false;
+ MaybeObject* result_object;
+ result_object = SetPropertyWithCallbackSetterInPrototypes(name,
+ value,
+ attributes,
+ &found,
+ strict_mode);
+ if (found) return result_object;
+ }
+
+ // At this point, no GC should have happened, as this would invalidate
+ // 'result', which we cannot handlify!
if (!result->IsFound()) {
// Neither properties nor transitions found.
« no previous file with comments | « src/objects.h ('k') | src/stub-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698