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

View File

@ -2148,13 +2148,6 @@ class JSObject: public JSReceiver {
StrictMode strict_mode, StrictMode strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); 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( MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
Handle<JSObject> object, Handle<JSObject> object,
Handle<Name> key, Handle<Name> key,
@ -2163,8 +2156,7 @@ class JSObject: public JSReceiver {
ValueType value_type = OPTIMAL_REPRESENTATION, ValueType value_type = OPTIMAL_REPRESENTATION,
StoreMode mode = ALLOW_AS_CONSTANT, StoreMode mode = ALLOW_AS_CONSTANT,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK, ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING);
static void AddProperty(Handle<JSObject> object, static void AddProperty(Handle<JSObject> object,
Handle<Name> key, Handle<Name> key,

View File

@ -5092,12 +5092,7 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate, result,
JSObject::SetOwnPropertyIgnoreAttributes( JSObject::SetOwnPropertyIgnoreAttributes(
js_object, name, obj_value, attr, 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));
return *result; return *result;
} }

View File

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

View File

@ -1136,7 +1136,8 @@ var objects = [
// createProxy(Proxy.create, null), // createProxy(Proxy.create, null),
// createProxy(Proxy.createFunction, function(){}), // 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. // Cases that yield non-standard results.
function blacklisted(obj, prop) { function blacklisted(obj, prop) {