Remove special ExecutableAccessorInfo handling based on flag

This additionally removes special "prototype" handling for O.o, since it's broken; and added test.

BUG=
R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/368853003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22171 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2014-07-02 15:28:29 +00:00
parent ec349cbfed
commit 2350d46146
5 changed files with 31 additions and 51 deletions

View File

@ -4219,8 +4219,7 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
ValueType value_type,
StoreMode mode,
ExtensibilityCheck extensibility_check,
StoreFromKeyed store_from_keyed,
ExecutableAccessorInfoHandling handling) {
StoreFromKeyed store_from_keyed) {
Isolate* isolate = object->GetIsolate();
// Make sure that the top context does not change when doing callbacks or
@ -4275,8 +4274,6 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
old_attributes = lookup.GetAttributes();
}
bool executed_set_prototype = false;
// Check of IsReadOnly removed from here in clone.
if (lookup.IsTransition()) {
Handle<Object> result;
@ -4300,11 +4297,9 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
}
break;
case CALLBACKS:
{
case CALLBACKS: {
Handle<Object> callback(lookup.GetCallbackObject(), isolate);
if (callback->IsExecutableAccessorInfo() &&
handling == DONT_FORCE_FIELD) {
if (callback->IsExecutableAccessorInfo()) {
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
@ -4316,31 +4311,29 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
STRICT),
Object);
if (attributes != lookup.GetAttributes()) {
Handle<ExecutableAccessorInfo> new_data =
Accessors::CloneAccessor(
isolate, Handle<ExecutableAccessorInfo>::cast(callback));
new_data->set_property_attributes(attributes);
if (attributes & READ_ONLY) {
// This way we don't have to introduce a lookup to the setter,
// simply make it unavailable to reflect the attributes.
new_data->clear_setter();
}
if (attributes == lookup.GetAttributes()) return result;
Handle<ExecutableAccessorInfo> new_data =
Accessors::CloneAccessor(
isolate, Handle<ExecutableAccessorInfo>::cast(callback));
new_data->set_property_attributes(attributes);
// This way we don't have to introduce a lookup to the setter, simply
// make it unavailable to reflect the attributes.
if (attributes & READ_ONLY) new_data->clear_setter();
SetPropertyCallback(object, name, new_data, attributes);
SetPropertyCallback(object, name, new_data, attributes);
}
if (is_observed) {
// If we are setting the prototype of a function and are observed,
// don't send change records because the prototype handles that
// itself.
executed_set_prototype = object->IsJSFunction() &&
String::Equals(isolate->factory()->prototype_string(),
Handle<String>::cast(name)) &&
Handle<JSFunction>::cast(object)->should_have_prototype();
Handle<Object> new_value =
Object::GetPropertyOrElement(object, name).ToHandleChecked();
if (old_value->SameValue(*new_value)) {
old_value = isolate->factory()->the_hole_value();
}
EnqueueChangeRecord(object, "reconfigure", name, old_value);
}
} else {
ConvertAndSetOwnProperty(&lookup, name, value, attributes);
return result;
}
ConvertAndSetOwnProperty(&lookup, name, value, attributes);
break;
}
case NONEXISTENT:
@ -4350,7 +4343,7 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
}
}
if (is_observed && !executed_set_prototype) {
if (is_observed) {
if (lookup.IsTransition()) {
EnqueueChangeRecord(object, "add", name, old_value);
} else if (old_value->IsTheHole()) {

View File

@ -2148,13 +2148,6 @@ class JSObject: public JSReceiver {
StrictMode strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to
// grant an exemption to ExecutableAccessor callbacks in some cases.
enum ExecutableAccessorInfoHandling {
DEFAULT_HANDLING,
DONT_FORCE_FIELD
};
MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<Name> key,
@ -2163,8 +2156,7 @@ class JSObject: public JSReceiver {
ValueType value_type = OPTIMAL_REPRESENTATION,
StoreMode mode = ALLOW_AS_CONSTANT,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING);
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
static void AddProperty(Handle<JSObject> object,
Handle<Name> key,

View File

@ -5092,12 +5092,7 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, obj_value, attr,
Object::OPTIMAL_REPRESENTATION,
ALLOW_AS_CONSTANT,
JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
JSReceiver::MAY_BE_STORE_FROM_KEYED,
JSObject::DONT_FORCE_FIELD));
js_object, name, obj_value, attr));
return *result;
}

View File

@ -15338,12 +15338,11 @@ TEST(ForceSet) {
CHECK_EQ(3, global->Get(access_property)->Int32Value());
CHECK_EQ(1, force_set_set_count);
CHECK_EQ(2, force_set_get_count);
// Forcing the property to be set should override the accessor without
// calling it
// Forcing the property to be set should call the accessor
global->ForceSet(access_property, v8::Int32::New(isolate, 8));
CHECK_EQ(8, global->Get(access_property)->Int32Value());
CHECK_EQ(1, force_set_set_count);
CHECK_EQ(2, force_set_get_count);
CHECK_EQ(3, global->Get(access_property)->Int32Value());
CHECK_EQ(2, force_set_set_count);
CHECK_EQ(3, force_set_get_count);
}

View File

@ -1136,7 +1136,8 @@ var objects = [
// createProxy(Proxy.create, null),
// createProxy(Proxy.createFunction, function(){}),
];
var properties = ["a", "1", 1, "length", "setPrototype", "name", "caller"];
var properties = ["a", "1", 1, "length", "setPrototype",
"name", "caller", "prototype"];
// Cases that yield non-standard results.
function blacklisted(obj, prop) {