Chromium Code Reviews| Index: src/runtime.cc | 
| diff --git a/src/runtime.cc b/src/runtime.cc | 
| index 07987e2e39e271da31ce4b88346de252736167f3..4345052058caf00bec8d2d9d31940e3e9200e1fc 100644 | 
| --- a/src/runtime.cc | 
| +++ b/src/runtime.cc | 
| @@ -200,6 +200,14 @@ static Handle<Map> ComputeObjectLiteralMap( | 
| } | 
| +MUST_USE_RESULT static MaybeHandle<Object> DefineOrRedefineDataProperty( | 
| + Isolate* isolate, | 
| + Handle<JSObject> object, | 
| + Handle<Name> name, | 
| + Handle<Object> value, | 
| + PropertyAttributes attr); | 
| + | 
| + | 
| MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 
| Isolate* isolate, | 
| Handle<FixedArray> literals, | 
| @@ -5169,28 +5177,12 @@ RUNTIME_FUNCTION(Runtime_DefineOrRedefineAccessorProperty) { | 
| } | 
| -// Implements part of 8.12.9 DefineOwnProperty. | 
| -// There are 3 cases that lead here: | 
| -// Step 4a - define a new data property. | 
| -// Steps 9b & 12 - replace an existing accessor property with a data property. | 
| -// Step 12 - update an existing data property with a data or generic | 
| -// descriptor. | 
| -RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) { | 
| - HandleScope scope(isolate); | 
| - ASSERT(args.length() == 4); | 
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); | 
| - CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 
| - CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); | 
| - CONVERT_SMI_ARG_CHECKED(unchecked, 3); | 
| - RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 
| - PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 
| - | 
| - // Check access rights if needed. | 
| - if (js_object->IsAccessCheckNeeded() && | 
| - !isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) { | 
| - return isolate->heap()->undefined_value(); | 
| - } | 
| - | 
| +static MaybeHandle<Object> DefineOrRedefineDataProperty( | 
| + Isolate* isolate, | 
| + Handle<JSObject> js_object, | 
| + Handle<Name> name, | 
| + Handle<Object> obj_value, | 
| + PropertyAttributes attr) { | 
| LookupResult lookup(isolate); | 
| js_object->LookupOwnRealNamedProperty(name, &lookup); | 
| @@ -5217,25 +5209,46 @@ RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) { | 
| // Use IgnoreAttributes version since a readonly property may be | 
| // overridden and SetProperty does not allow this. | 
| - Handle<Object> result; | 
| - 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)); | 
| - return *result; | 
| + return 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); | 
| + } | 
| + | 
| + return Runtime::ForceSetObjectProperty( | 
| + js_object, name, obj_value, attr, | 
| + JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED); | 
| +} | 
| + | 
| + | 
| +// Implements part of 8.12.9 DefineOwnProperty. | 
| +// There are 3 cases that lead here: | 
| +// Step 4a - define a new data property. | 
| +// Steps 9b & 12 - replace an existing accessor property with a data property. | 
| +// Step 12 - update an existing data property with a data or generic | 
| +// descriptor. | 
| +RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) { | 
| + HandleScope scope(isolate); | 
| + ASSERT(args.length() == 4); | 
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); | 
| + CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 
| + CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); | 
| + CONVERT_SMI_ARG_CHECKED(unchecked, 3); | 
| + RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 
| + PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 
| + | 
| + // Check access rights if needed. | 
| + if (js_object->IsAccessCheckNeeded() && | 
| + !isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) { | 
| + return isolate->heap()->undefined_value(); | 
| } | 
| Handle<Object> result; | 
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
| - isolate, result, | 
| - Runtime::ForceSetObjectProperty( | 
| - js_object, name, obj_value, attr, | 
| - JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED)); | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 
| + DefineOrRedefineDataProperty(isolate, js_object, name, obj_value, attr)); | 
| return *result; | 
| } | 
| @@ -5481,6 +5494,74 @@ RUNTIME_FUNCTION(Runtime_SetProperty) { | 
| } | 
| +// This function is only used on object literals. | 
| +static MaybeHandle<Object> PutOwnElement(Isolate* isolate, | 
| 
 
rossberg
2014/06/13 15:19:24
Nit: SetOwnElement
 
wingo
2014/06/16 08:32:27
Done.
 
 | 
| + Handle<JSObject> object, | 
| + uint32_t index, | 
| + Handle<Object> value) { | 
| + StrictMode strict_mode = SLOPPY; | 
| + | 
| + JSObject::ValidateElements(object); | 
| + | 
| + // Object literals don't have these. | 
| + ASSERT(!object->HasExternalArrayElements()); | 
| + ASSERT(!object->HasFixedTypedArrayElements()); | 
| + | 
| + // It is currently impossible for an object literal to have a getter or a | 
| + // setter for an element, though this may change when we have computed | 
| + // accessor property names. | 
| + MaybeHandle<Object> result = JSObject::SetOwnElement( | 
| + object, index, value, strict_mode); | 
| + JSObject::ValidateElements(object); | 
| + | 
| + return result.is_null() ? result : value; | 
| +} | 
| + | 
| + | 
| +static MaybeHandle<Object> PutOwnProperty(Isolate* isolate, | 
| 
 
rossberg
2014/06/13 15:19:24
Nit: SetOwnProperty
 
wingo
2014/06/16 08:32:27
Done.
 
 | 
| + Handle<JSObject> object, | 
| + Handle<Object> key, | 
| + Handle<Object> value) { | 
| + PropertyAttributes attr = NONE; | 
| + | 
| + // Check if the given key is an array index. | 
| + uint32_t index; | 
| + if (key->ToArrayIndex(&index)) { | 
| + return PutOwnElement(isolate, object, index, value); | 
| + } | 
| + | 
| + if (!key->IsName()) { | 
| + // Call back into JavaScript to convert the key to a string. | 
| + ASSIGN_RETURN_ON_EXCEPTION( | 
| + isolate, key, Execution::ToString(isolate, key), Object); | 
| + } | 
| + | 
| + Handle<Name> name = Handle<Name>::cast(key); | 
| + if (name->AsArrayIndex(&index)) { | 
| + return PutOwnElement(isolate, object, index, value); | 
| + } | 
| + | 
| + return DefineOrRedefineDataProperty(isolate, object, name, value, attr); | 
| +} | 
| + | 
| + | 
| +// Used to initialize data properties on object literals. We know that the | 
| +// attributes will be NONE. | 
| +RUNTIME_FUNCTION(Runtime_PutOwnProperty) { | 
| + HandleScope scope(isolate); | 
| + RUNTIME_ASSERT(args.length() == 3); | 
| + | 
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 
| + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | 
| + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 
| + | 
| + Handle<Object> result; | 
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 
| + PutOwnProperty(isolate, object, key, value)); | 
| + return *result; | 
| +} | 
| + | 
| + | 
| RUNTIME_FUNCTION(Runtime_TransitionElementsKind) { | 
| HandleScope scope(isolate); | 
| RUNTIME_ASSERT(args.length() == 2); |