| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 07987e2e39e271da31ce4b88346de252736167f3..0ac8ef10489910ed33cbbbd38bfa3a04a8572ecc 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> SetOwnElement(Isolate* isolate,
|
| + 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> SetOwnProperty(Isolate* isolate,
|
| + 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 SetOwnElement(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 SetOwnElement(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_SetOwnProperty) {
|
| + 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,
|
| + SetOwnProperty(isolate, object, key, value));
|
| + return *result;
|
| +}
|
| +
|
| +
|
| RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
|
| HandleScope scope(isolate);
|
| RUNTIME_ASSERT(args.length() == 2);
|
|
|