Revert of Replace SetObjectProperty / DefineObjectProperty with less powerful alterna...
authorishell <ishell@chromium.org>
Thu, 11 Jun 2015 17:21:11 +0000 (10:21 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 11 Jun 2015 17:21:19 +0000 (17:21 +0000)
Reason for revert:
Blocks revert of https://codereview.chromium.org/1175973002

Original issue's description:
> Replace SetObjectProperty / DefineObjectProperty with less powerful alternatives where relevant.
>
> @yangguo: please look at the debugger part of the CL.
> @ishell: please look at the rest.
>
> Additionally:
> - Ensure the LookupIterator for named properties does not accidentally get indexes in.
> - Fix the return value for typed array assignments to be the incoming value.
>
> BUG=v8:4137
> LOG=n
>
> Committed: https://crrev.com/15aa811f8fe2708a757c3b53ca89db736aa8b222
> Cr-Commit-Position: refs/heads/master@{#28954}

TBR=yangguo@chromium.org,verwaest@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:4137

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

Cr-Commit-Position: refs/heads/master@{#28957}

16 files changed:
src/api-natives.cc
src/api.cc
src/bootstrapper.cc
src/ic/ic.cc
src/json-parser.h
src/lookup.cc
src/lookup.h
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime/runtime-classes.cc
src/runtime/runtime-debug.cc
src/runtime/runtime-object.cc
src/runtime/runtime.h
src/scopeinfo.cc
test/cctest/test-debug.cc

index 74518447ea329a61a703cd66fa459d5ca2b1ee4f..71a039f35ea8d4d312e43a398392630190618163 100644 (file)
@@ -80,24 +80,32 @@ MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
                              Instantiate(isolate, prop_data, key), Object);
 
-  uint32_t index = 0;
-  LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
-  LookupIterator it = key->AsArrayIndex(&index)
-                          ? LookupIterator(isolate, object, index, c)
-                          : LookupIterator(object, key, c);
-
 #ifdef DEBUG
-  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
-  DCHECK(maybe.IsJust());
-  if (it.IsFound()) {
+  bool duplicate;
+  if (key->IsName()) {
+    LookupIterator it(object, Handle<Name>::cast(key),
+                      LookupIterator::OWN_SKIP_INTERCEPTOR);
+    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
+    DCHECK(maybe.IsJust());
+    duplicate = it.IsFound();
+  } else {
+    uint32_t index = 0;
+    key->ToArrayIndex(&index);
+    Maybe<bool> maybe = JSReceiver::HasOwnElement(object, index);
+    if (!maybe.IsJust()) return MaybeHandle<Object>();
+    duplicate = maybe.FromJust();
+  }
+  if (duplicate) {
     THROW_NEW_ERROR(
         isolate, NewTypeError(MessageTemplate::kDuplicateTemplateProperty, key),
         Object);
   }
 #endif
 
-  return Object::AddDataProperty(&it, value, attributes, STRICT,
-                                 Object::CERTAINLY_NOT_STORE_FROM_KEYED);
+  RETURN_ON_EXCEPTION(
+      isolate, Runtime::DefineObjectProperty(object, key, value, attributes),
+      Object);
+  return object;
 }
 
 
index 0bd435b738b64bb11e3d6a586e7a2217f04fdbdf..b8812800081d1b36ea84b5871c2a80a8d870bb93 100644 (file)
@@ -3535,7 +3535,7 @@ Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
 
   if (it.IsFound() && !it.IsConfigurable()) return Just(false);
 
-  has_pending_exception = i::JSObject::SetOwnPropertyIgnoreAttributes(
+  has_pending_exception = i::Runtime::DefineObjectProperty(
                               self, key_obj, value_obj, NONE).is_null();
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
   return Just(true);
@@ -3573,8 +3573,9 @@ Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
     return Just(false);
   }
 
-  has_pending_exception = i::JSObject::SetOwnElementIgnoreAttributes(
-                              self, index, value_obj, NONE).is_null();
+  has_pending_exception = i::Runtime::DefineObjectProperty(
+                              self, isolate->factory()->Uint32ToString(index),
+                              value_obj, NONE).is_null();
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
   return Just(true);
 }
@@ -3612,34 +3613,6 @@ Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context,
 }
 
 
-MUST_USE_RESULT
-static i::MaybeHandle<i::Object> DefineObjectProperty(
-    i::Handle<i::JSObject> js_object, i::Handle<i::Object> key,
-    i::Handle<i::Object> value, PropertyAttributes attrs) {
-  i::Isolate* isolate = js_object->GetIsolate();
-  // Check if the given key is an array index.
-  uint32_t index = 0;
-  if (key->ToArrayIndex(&index)) {
-    return i::JSObject::SetOwnElementIgnoreAttributes(js_object, index, value,
-                                                      attrs);
-  }
-
-  i::Handle<i::Name> name;
-  if (key->IsName()) {
-    name = i::Handle<i::Name>::cast(key);
-  } else {
-    // Call-back into JavaScript to convert the key to a string.
-    i::Handle<i::Object> converted;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, converted,
-                                     i::Execution::ToString(isolate, key),
-                                     i::MaybeHandle<i::Object>());
-    name = i::Handle<i::String>::cast(converted);
-  }
-
-  return i::JSObject::DefinePropertyOrElement(js_object, name, value, attrs);
-}
-
-
 Maybe<bool> v8::Object::ForceSet(v8::Local<v8::Context> context,
                                  v8::Local<Value> key, v8::Local<Value> value,
                                  v8::PropertyAttribute attribs) {
@@ -3647,9 +3620,11 @@ Maybe<bool> v8::Object::ForceSet(v8::Local<v8::Context> context,
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   auto value_obj = Utils::OpenHandle(*value);
-  has_pending_exception =
-      DefineObjectProperty(self, key_obj, value_obj,
-                           static_cast<PropertyAttributes>(attribs)).is_null();
+  has_pending_exception = i::Runtime::DefineObjectProperty(
+      self,
+      key_obj,
+      value_obj,
+      static_cast<PropertyAttributes>(attribs)).is_null();
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
   return Just(true);
 }
@@ -3665,8 +3640,9 @@ bool v8::Object::ForceSet(v8::Handle<Value> key, v8::Handle<Value> value,
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
   has_pending_exception =
-      DefineObjectProperty(self, key_obj, value_obj,
-                           static_cast<PropertyAttributes>(attribs)).is_null();
+      i::Runtime::DefineObjectProperty(self, key_obj, value_obj,
+                                       static_cast<PropertyAttributes>(attribs))
+          .is_null();
   EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, false);
   return true;
 }
index f4768de3a9e281efd7ccd73113acdd7184c31954..c675fe7e0d423211669c505a2f1a7a4169a9aa31 100644 (file)
@@ -940,9 +940,8 @@ void Genesis::HookUpGlobalObject(Handle<GlobalObject> global_object,
 
   static const PropertyAttributes attributes =
       static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
-  JSObject::SetOwnPropertyIgnoreAttributes(builtins_global,
-                                           factory()->global_string(),
-                                           global_object, attributes).Assert();
+  Runtime::DefineObjectProperty(builtins_global, factory()->global_string(),
+                                global_object, attributes).Assert();
   // Set up the reference from the global object to the builtins object.
   JSGlobalObject::cast(*global_object)->set_builtins(*builtins_global);
   TransferNamedProperties(global_object_from_snapshot, global_object);
index d04fc583c44a909cc0d57c900a7da160c88236aa..c0d8e005abedeb32ce95b1d70c396e590e24a719 100644 (file)
@@ -1226,7 +1226,7 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
     } else {
       int int_value = FastD2I(value);
       if (value == int_value && Smi::IsValid(int_value)) {
-        key = handle(Smi::FromInt(int_value), isolate);
+        key = Handle<Smi>(Smi::FromInt(int_value), isolate);
       }
     }
   } else if (key->IsUndefined()) {
index 8ed2e84059cfb7aa9fe74e4ff0b3db16ae71cc45..9234e85aa20d171fcad6a1f27a5317457debee1b 100644 (file)
@@ -434,7 +434,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
       // Commit the intermediate state to the object and stop transitioning.
       CommitStateToJsonObject(json_object, map, &properties);
 
-      JSObject::DefinePropertyOrElement(json_object, key, value).Check();
+      Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
     } while (transitioning && MatchSkipWhiteSpace(','));
 
     // If we transitioned until the very end, transition the map now.
@@ -470,7 +470,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
         value = ParseJsonValue();
         if (value.is_null()) return ReportUnexpectedCharacter();
 
-        JSObject::DefinePropertyOrElement(json_object, key, value).Check();
+        Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
       }
     }
 
index 6a26663b44f87380dfaf9efb5ed16b57467e35ca..1bb491a9dee2aa528f1a85de8a9756f99c8143bf 100644 (file)
@@ -419,12 +419,12 @@ Handle<Object> LookupIterator::GetDataValue() const {
 }
 
 
-void LookupIterator::WriteDataValue(Handle<Object> value) {
+Handle<Object> LookupIterator::WriteDataValue(Handle<Object> value) {
   DCHECK_EQ(DATA, state_);
   Handle<JSObject> holder = GetHolder<JSObject>();
   if (IsElement()) {
     ElementsAccessor* accessor = holder->GetElementsAccessor();
-    accessor->Set(holder, index_, value);
+    return accessor->Set(holder, index_, value);
   } else if (holder->IsGlobalObject()) {
     Handle<GlobalDictionary> property_dictionary =
         handle(holder->global_dictionary());
@@ -439,6 +439,7 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
   } else {
     DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type());
   }
+  return value;
 }
 
 
index 48604b2389a375da7a99dd09bea37e217bfb3062..be8394afec4e7242fd294695f6b31f347dac8628 100644 (file)
@@ -59,10 +59,12 @@ class LookupIterator final BASE_EMBEDDED {
         holder_map_(holder_->map(), isolate_),
         initial_holder_(holder_),
         number_(DescriptorArray::kNotFound) {
+#if 0  // TODO(verwaest): Enable once blocking hacks are removed.
 #ifdef DEBUG
     uint32_t index;  // Assert that the name is not an array index.
     DCHECK(!name->AsArrayIndex(&index));
 #endif  // DEBUG
+#endif
     Next();
   }
 
@@ -83,10 +85,12 @@ class LookupIterator final BASE_EMBEDDED {
         holder_map_(holder_->map(), isolate_),
         initial_holder_(holder_),
         number_(DescriptorArray::kNotFound) {
+#if 0  // TODO(verwaest): Enable once blocking hacks are removed.
 #ifdef DEBUG
     uint32_t index;  // Assert that the name is not an array index.
     DCHECK(!name->AsArrayIndex(&index));
 #endif  // DEBUG
+#endif
     Next();
   }
 
@@ -208,7 +212,9 @@ class LookupIterator final BASE_EMBEDDED {
   Handle<Object> GetAccessors() const;
   Handle<InterceptorInfo> GetInterceptor() const;
   Handle<Object> GetDataValue() const;
-  void WriteDataValue(Handle<Object> value);
+  // Usually returns the value that was passed in. In case of typed array
+  // accesses it returns the converted value.
+  Handle<Object> WriteDataValue(Handle<Object> value);
   void InternalizeName();
 
  private:
index 501eef4c20086a1d2361542b0117d0eb1a868340..27528d644253793d8418fc019ec183557cd52c31 100644 (file)
@@ -1197,20 +1197,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
 }
 
 
-MaybeHandle<Object> JSObject::DefinePropertyOrElement(
-    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
-    PropertyAttributes attributes) {
-  uint32_t index;
-  if (name->AsArrayIndex(&index)) {
-    return SetOwnElementIgnoreAttributes(object, index, value, attributes);
-  }
-
-  // TODO(verwaest): Is this necessary?
-  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
-  return SetOwnPropertyIgnoreAttributes(object, name, value, attributes);
-}
-
-
 #define FIELD_ADDR(p, offset) \
   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
 
index 7e402184b1f5e1c82cc9fa6719ed363f50393e13..180255f4fd39cca153b7323c0d1c1f990224322e 100644 (file)
@@ -3223,6 +3223,17 @@ MaybeHandle<Object> Object::WriteToReadOnlyProperty(
 }
 
 
+MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
+                                                   Handle<Object> receiver,
+                                                   uint32_t index,
+                                                   Handle<Object> value,
+                                                   LanguageMode language_mode) {
+  return WriteToReadOnlyProperty(isolate, receiver,
+                                 isolate->factory()->NewNumberFromUint(index),
+                                 value, language_mode);
+}
+
+
 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
     Isolate* isolate, Handle<Object> name, Handle<Object> value,
     LanguageMode language_mode) {
@@ -3251,12 +3262,11 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
   MaybeHandle<Object> maybe_old;
   if (is_observed) maybe_old = it->GetDataValue();
 
-  Handle<Object> to_assign = value;
   // Convert the incoming value to a number for storing into typed arrays.
   if (it->IsElement() && (receiver->HasExternalArrayElements() ||
                           receiver->HasFixedTypedArrayElements())) {
     if (!value->IsNumber() && !value->IsUndefined()) {
-      ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
+      ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), value,
                                  Execution::ToNumber(it->isolate(), value),
                                  Object);
     }
@@ -3264,10 +3274,10 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
 
   // Possibly migrate to the most up-to-date map that will be able to store
   // |value| under it->name().
-  it->PrepareForDataProperty(to_assign);
+  it->PrepareForDataProperty(value);
 
   // Write the property value.
-  it->WriteDataValue(to_assign);
+  value = it->WriteDataValue(value);
 
   // Send the change record if there are observers.
   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
@@ -4244,7 +4254,7 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
   DCHECK(!value->IsTheHole());
   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   if (it.state() == LookupIterator::ACCESS_CHECK) {
-    if (!it.HasAccess()) {
+    if (!it.isolate()->MayAccess(object)) {
       return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
     }
     it.Next();
@@ -4267,7 +4277,7 @@ MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
   LookupIterator it(isolate, object, index,
                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   if (it.state() == LookupIterator::ACCESS_CHECK) {
-    if (!it.HasAccess()) {
+    if (!isolate->MayAccess(object)) {
       return SetPropertyWithFailedAccessCheck(&it, value, STRICT);
     }
     it.Next();
index 5ce906152bf6e4b886dc2fe3d250ac6ad159cc98..bd9e4abe71354c1936cb5bac273dfa645fc2a0cb 100644 (file)
@@ -1176,6 +1176,9 @@ class Object {
   MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
       Isolate* isolate, Handle<Object> reciever, Handle<Object> name,
       Handle<Object> value, LanguageMode language_mode);
+  MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyElement(
+      Isolate* isolate, Handle<Object> receiver, uint32_t index,
+      Handle<Object> value, LanguageMode language_mode);
   MUST_USE_RESULT static MaybeHandle<Object> RedefineNonconfigurableProperty(
       Isolate* isolate, Handle<Object> name, Handle<Object> value,
       LanguageMode language_mode);
@@ -1838,12 +1841,6 @@ class JSObject: public JSReceiver {
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor(
       LookupIterator* it, Handle<Object> value);
 
-  // Calls SetOwn[Property|Element]IgnoreAttributes depending on whether name is
-  // convertible to an index.
-  MUST_USE_RESULT static inline MaybeHandle<Object> DefinePropertyOrElement(
-      Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
-      PropertyAttributes attributes = NONE);
-
   MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
       Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
       PropertyAttributes attributes);
@@ -4048,7 +4045,7 @@ class ScopeInfo : public FixedArray {
   FunctionKind function_kind();
 
   // Copies all the context locals into an object used to materialize a scope.
-  static void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
+  static bool CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
                                              Handle<Context> context,
                                              Handle<JSObject> scope_object);
 
index fe76dfa0dd2564c9787cb9d806084cb74eea4f23..3dbcc65eca6af1e5e5e9a0f80009d18dd8a73640 100644 (file)
@@ -200,8 +200,16 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
 
-  RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::DefinePropertyOrElement(
-                                           object, name, function, DONT_ENUM));
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) {
+    RETURN_FAILURE_ON_EXCEPTION(
+        isolate, JSObject::SetOwnElementIgnoreAttributes(object, index,
+                                                         function, DONT_ENUM));
+  } else {
+    RETURN_FAILURE_ON_EXCEPTION(
+        isolate, JSObject::SetOwnPropertyIgnoreAttributes(object, name,
+                                                          function, DONT_ENUM));
+  }
   return isolate->heap()->undefined_value();
 }
 
index 5ae797986eefdb93bd0897f7bd2990d30bf09ef1..2555086b07e2265ad7da2b00088bdf316b804d5c 100644 (file)
@@ -861,10 +861,11 @@ static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
 }
 
 
-static Handle<Context> MaterializeReceiver(Isolate* isolate,
-                                           Handle<Context> target,
-                                           Handle<JSFunction> function,
-                                           JavaScriptFrame* frame) {
+MUST_USE_RESULT
+static MaybeHandle<Context> MaterializeReceiver(Isolate* isolate,
+                                                Handle<Context> target,
+                                                Handle<JSFunction> function,
+                                                JavaScriptFrame* frame) {
   Handle<SharedFunctionInfo> shared(function->shared());
   Handle<ScopeInfo> scope_info(shared->scope_info());
   Handle<Object> receiver;
@@ -881,14 +882,14 @@ static Handle<Context> MaterializeReceiver(Isolate* isolate,
               &init_flag, &maybe_assigned_flag) >= 0) {
         return target;
       }
-      receiver = handle(frame->receiver(), isolate);
+      receiver = Handle<Object>(frame->receiver(), isolate);
       break;
     }
     case MODULE_SCOPE:
       receiver = isolate->factory()->undefined_value();
       break;
     case SCRIPT_SCOPE:
-      receiver = handle(function->global_proxy(), isolate);
+      receiver = Handle<Object>(function->global_proxy(), isolate);
       break;
     default:
       // For eval code, arrow functions, and the like, there's no "this" binding
@@ -903,7 +904,8 @@ static Handle<Context> MaterializeReceiver(Isolate* isolate,
 
 // Create a plain JSObject which materializes the local scope for the specified
 // frame.
-static void MaterializeStackLocalsWithFrameInspector(
+MUST_USE_RESULT
+static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
     Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info,
     FrameInspector* frame_inspector) {
   // First fill all parameters.
@@ -921,7 +923,9 @@ static void MaterializeStackLocalsWithFrameInspector(
                          isolate);
     DCHECK(!value->IsTheHole());
 
-    JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
+    RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty(
+                                     isolate, target, name, value, SLOPPY),
+                        JSObject);
   }
 
   // Second fill all stack locals.
@@ -935,18 +939,23 @@ static void MaterializeStackLocalsWithFrameInspector(
       value = isolate->factory()->undefined_value();
     }
 
-    JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
+    RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty(
+                                     isolate, target, name, value, SLOPPY),
+                        JSObject);
   }
+
+  return target;
 }
 
-static void MaterializeStackLocalsWithFrameInspector(
+MUST_USE_RESULT
+static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
     Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function,
     FrameInspector* frame_inspector) {
   Handle<SharedFunctionInfo> shared(function->shared());
   Handle<ScopeInfo> scope_info(shared->scope_info());
 
-  MaterializeStackLocalsWithFrameInspector(isolate, target, scope_info,
-                                           frame_inspector);
+  return MaterializeStackLocalsWithFrameInspector(isolate, target, scope_info,
+                                                  frame_inspector);
 }
 
 
@@ -999,8 +1008,10 @@ MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext(
   // Third fill all context locals.
   Handle<Context> frame_context(Context::cast(frame->context()));
   Handle<Context> function_context(frame_context->declaration_context());
-  ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context,
-                                            target);
+  if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context,
+                                                 target)) {
+    return MaybeHandle<JSObject>();
+  }
 
   // Finally copy any properties from the function context extension.
   // These will be variables introduced by eval.
@@ -1045,8 +1056,10 @@ MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScriptScope(
     Handle<Context> context =
         ScriptContextTable::GetContext(script_contexts, context_index);
     Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
-    ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
-                                              script_scope);
+    if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
+                                                   script_scope)) {
+      return MaybeHandle<JSObject>();
+    }
   }
   return script_scope;
 }
@@ -1059,8 +1072,11 @@ MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope(
 
   Handle<JSObject> local_scope =
       isolate->factory()->NewJSObject(isolate->object_function());
-  MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function,
-                                           &frame_inspector);
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, local_scope,
+      MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function,
+                                               &frame_inspector),
+      JSObject);
 
   return MaterializeLocalContext(isolate, local_scope, function, frame);
 }
@@ -1180,8 +1196,8 @@ static bool SetBlockVariableValue(Isolate* isolate,
 
 // Create a plain JSObject which materializes the closure content for the
 // context.
-static Handle<JSObject> MaterializeClosure(Isolate* isolate,
-                                           Handle<Context> context) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure(
+    Isolate* isolate, Handle<Context> context) {
   DCHECK(context->IsFunctionContext());
 
   Handle<SharedFunctionInfo> shared(context->closure()->shared());
@@ -1193,24 +1209,31 @@ static Handle<JSObject> MaterializeClosure(Isolate* isolate,
       isolate->factory()->NewJSObject(isolate->object_function());
 
   // Fill all context locals to the context extension.
-  ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, closure_scope);
+  if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
+                                                 closure_scope)) {
+    return MaybeHandle<JSObject>();
+  }
 
   // Finally copy any properties from the function context extension. This will
   // be variables introduced by eval.
   if (context->has_extension()) {
     Handle<JSObject> ext(JSObject::cast(context->extension()));
-    DCHECK(ext->IsJSContextExtensionObject());
-    Handle<FixedArray> keys =
-        JSReceiver::GetKeys(ext, JSReceiver::OWN_ONLY).ToHandleChecked();
+    Handle<FixedArray> keys;
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
+        JSObject);
 
     for (int i = 0; i < keys->length(); i++) {
       HandleScope scope(isolate);
       // Names of variables introduced by eval are strings.
       DCHECK(keys->get(i)->IsString());
       Handle<String> key(String::cast(keys->get(i)));
-      Handle<Object> value = Object::GetProperty(ext, key).ToHandleChecked();
-      JSObject::SetOwnPropertyIgnoreAttributes(closure_scope, key, value, NONE)
-          .Check();
+      Handle<Object> value;
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
+      RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
+                                       closure_scope, key, value, NONE),
+                          JSObject);
     }
   }
 
@@ -1237,13 +1260,12 @@ static bool SetClosureVariableValue(Isolate* isolate, Handle<Context> context,
   // be variables introduced by eval.
   if (context->has_extension()) {
     Handle<JSObject> ext(JSObject::cast(context->extension()));
-    DCHECK(ext->IsJSContextExtensionObject());
-    Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
+    Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
     DCHECK(maybe.IsJust());
     if (maybe.FromJust()) {
       // We don't expect this to do anything except replacing property value.
-      JSObject::SetOwnPropertyIgnoreAttributes(ext, variable_name, new_value,
-                                               NONE).Check();
+      Runtime::DefineObjectProperty(ext, variable_name, new_value, NONE)
+          .Assert();
       return true;
     }
   }
@@ -1272,16 +1294,17 @@ static bool SetScriptVariableValue(Handle<Context> context,
 
 // Create a plain JSObject which materializes the scope for the specified
 // catch context.
-static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
-                                              Handle<Context> context) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope(
+    Isolate* isolate, Handle<Context> context) {
   DCHECK(context->IsCatchContext());
   Handle<String> name(String::cast(context->extension()));
   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
                                isolate);
   Handle<JSObject> catch_scope =
       isolate->factory()->NewJSObject(isolate->object_function());
-  JSObject::SetOwnPropertyIgnoreAttributes(catch_scope, name, thrown_object,
-                                           NONE).Check();
+  RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
+                                   catch_scope, name, thrown_object, NONE),
+                      JSObject);
   return catch_scope;
 }
 
@@ -1301,26 +1324,28 @@ static bool SetCatchVariableValue(Isolate* isolate, Handle<Context> context,
 
 // Create a plain JSObject which materializes the block scope for the specified
 // block context.
-static Handle<JSObject> MaterializeBlockScope(Isolate* isolate,
-                                              Handle<ScopeInfo> scope_info,
-                                              Handle<Context> context,
-                                              JavaScriptFrame* frame,
-                                              int inlined_jsframe_index) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope(
+    Isolate* isolate, Handle<ScopeInfo> scope_info, Handle<Context> context,
+    JavaScriptFrame* frame, int inlined_jsframe_index) {
   Handle<JSObject> block_scope =
       isolate->factory()->NewJSObject(isolate->object_function());
 
   if (frame != nullptr) {
     FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
-    MaterializeStackLocalsWithFrameInspector(isolate, block_scope, scope_info,
-                                             &frame_inspector);
+    RETURN_ON_EXCEPTION(isolate,
+                        MaterializeStackLocalsWithFrameInspector(
+                            isolate, block_scope, scope_info, &frame_inspector),
+                        JSObject);
   }
 
   if (!context.is_null()) {
     Handle<ScopeInfo> scope_info_from_context(
         ScopeInfo::cast(context->extension()));
     // Fill all context locals.
-    ScopeInfo::CopyContextLocalsToScopeObject(scope_info_from_context, context,
-                                              block_scope);
+    if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info_from_context,
+                                                   context, block_scope)) {
+      return MaybeHandle<JSObject>();
+    }
   }
 
   return block_scope;
@@ -1340,7 +1365,10 @@ MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope(
       isolate->factory()->NewJSObject(isolate->object_function());
 
   // Fill all context locals.
-  ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, module_scope);
+  if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context,
+                                                 module_scope)) {
+    return MaybeHandle<JSObject>();
+  }
 
   return module_scope;
 }
@@ -2368,23 +2396,24 @@ RUNTIME_FUNCTION(Runtime_ClearStepping) {
 
 // Helper function to find or create the arguments object for
 // Runtime_DebugEvaluate.
-static void MaterializeArgumentsObject(Isolate* isolate,
-                                       Handle<JSObject> target,
-                                       Handle<JSFunction> function) {
+MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
+    Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function) {
   // Do not materialize the arguments object for eval or top-level code.
   // Skip if "arguments" is already taken.
-  if (!function->shared()->is_function()) return;
+  if (!function->shared()->is_function()) return target;
   Maybe<bool> maybe = JSReceiver::HasOwnProperty(
       target, isolate->factory()->arguments_string());
-  DCHECK(maybe.IsJust());
-  if (maybe.FromJust()) return;
+  if (!maybe.IsJust()) return MaybeHandle<JSObject>();
+  if (maybe.FromJust()) return target;
 
   // FunctionGetArguments can't throw an exception.
   Handle<JSObject> arguments =
       Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
   Handle<String> arguments_str = isolate->factory()->arguments_string();
-  JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
-                                           NONE).Check();
+  RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty(
+                                   target, arguments_str, arguments, NONE),
+                      JSObject);
+  return target;
 }
 
 
@@ -2481,16 +2510,22 @@ class EvaluationContextBuilder {
 
         // The "this" binding, if any, can't be bound via "with".  If we need
         // to, add another node onto the outer context to bind "this".
-        parent_context =
-            MaterializeReceiver(isolate, parent_context, function, frame);
+        if (!MaterializeReceiver(isolate, parent_context, function, frame)
+                 .ToHandle(&parent_context))
+          return;
 
         Handle<JSObject> materialized_function =
             NewJSObjectWithNullProto(isolate);
 
-        MaterializeStackLocalsWithFrameInspector(isolate, materialized_function,
-                                                 function, &frame_inspector);
+        if (!MaterializeStackLocalsWithFrameInspector(
+                 isolate, materialized_function, function, &frame_inspector)
+                 .ToHandle(&materialized_function))
+          return;
 
-        MaterializeArgumentsObject(isolate, materialized_function, function);
+        if (!MaterializeArgumentsObject(isolate, materialized_function,
+                                        function)
+                 .ToHandle(&materialized_function))
+          return;
 
         Handle<Context> with_context = isolate->factory()->NewWithContext(
             function, parent_context, materialized_function);
@@ -2518,9 +2553,10 @@ class EvaluationContextBuilder {
       } else if (scope_type == ScopeIterator::ScopeTypeBlock) {
         Handle<JSObject> materialized_object =
             NewJSObjectWithNullProto(isolate);
-        MaterializeStackLocalsWithFrameInspector(isolate, materialized_object,
-                                                 it.CurrentScopeInfo(),
-                                                 &frame_inspector);
+        if (!MaterializeStackLocalsWithFrameInspector(
+                 isolate, materialized_object, it.CurrentScopeInfo(),
+                 &frame_inspector).ToHandle(&materialized_object))
+          return;
         if (it.HasContext()) {
           Handle<Context> cloned_context =
               Handle<Context>::cast(FixedArray::CopySize(
index 1bf405a1d9a9bd4d533a354ee45252b972102bf9..956fee9e838f46214ed47b017e7a0a226efedf99 100644 (file)
@@ -92,13 +92,98 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
         Object);
   }
 
+  if (object->IsJSProxy()) {
+    Handle<Object> name_object;
+    if (key->IsSymbol()) {
+      name_object = key;
+    } else {
+      ASSIGN_RETURN_ON_EXCEPTION(isolate, name_object,
+                                 Execution::ToString(isolate, key), Object);
+    }
+    Handle<Name> name = Handle<Name>::cast(name_object);
+    return Object::SetProperty(Handle<JSProxy>::cast(object), name, value,
+                               language_mode);
+  }
+
+  // Check if the given key is an array index.
+  uint32_t index = 0;
+  if (key->ToArrayIndex(&index)) {
+    // TODO(verwaest): Support non-JSObject receivers.
+    if (!object->IsJSObject()) return value;
+    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+
+    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
+    // of a string using [] notation.  We need to support this too in
+    // JavaScript.
+    // In the case of a String object we just need to redirect the assignment to
+    // the underlying string if the index is in range.  Since the underlying
+    // string does nothing with the assignment then we can ignore such
+    // assignments.
+    if (js_object->IsStringObjectWithCharacterAt(index)) {
+      return value;
+    }
+
+    JSObject::ValidateElements(js_object);
+    if (js_object->HasExternalArrayElements() ||
+        js_object->HasFixedTypedArrayElements()) {
+      if (!value->IsNumber() && !value->IsUndefined()) {
+        ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
+                                   Execution::ToNumber(isolate, value), Object);
+      }
+    }
+
+    MaybeHandle<Object> result =
+        JSObject::SetElement(js_object, index, value, language_mode);
+    JSObject::ValidateElements(js_object);
+
+    return result.is_null() ? result : value;
+  }
+
+  if (key->IsName()) {
+    Handle<Name> name = Handle<Name>::cast(key);
+    if (name->AsArrayIndex(&index)) {
+      // TODO(verwaest): Support non-JSObject receivers.
+      if (!object->IsJSObject()) return value;
+      Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+      if (js_object->HasExternalArrayElements()) {
+        if (!value->IsNumber() && !value->IsUndefined()) {
+          ASSIGN_RETURN_ON_EXCEPTION(
+              isolate, value, Execution::ToNumber(isolate, value), Object);
+        }
+      }
+      return JSObject::SetElement(js_object, index, value, language_mode);
+    } else {
+      if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
+      return Object::SetProperty(object, name, value, language_mode);
+    }
+  }
+
+  // Call-back into JavaScript to convert the key to a string.
+  Handle<Object> converted;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
+                             Execution::ToString(isolate, key), Object);
+  Handle<String> name = Handle<String>::cast(converted);
+
+  if (name->AsArrayIndex(&index)) {
+    // TODO(verwaest): Support non-JSObject receivers.
+    if (!object->IsJSObject()) return value;
+    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+    return JSObject::SetElement(js_object, index, value, language_mode);
+  }
+  return Object::SetProperty(object, name, value, language_mode);
+}
+
+
+MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
+                                                  Handle<Object> key,
+                                                  Handle<Object> value,
+                                                  PropertyAttributes attrs) {
+  Isolate* isolate = js_object->GetIsolate();
   // Check if the given key is an array index.
   uint32_t index = 0;
   if (key->ToArrayIndex(&index)) {
-    // TODO(verwaest): Support other objects as well.
-    if (!object->IsJSReceiver()) return value;
-    return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
-                                  value, language_mode);
+    return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value,
+                                                   attrs);
   }
 
   Handle<Name> name;
@@ -113,12 +198,13 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
   }
 
   if (name->AsArrayIndex(&index)) {
-    // TODO(verwaest): Support other objects as well.
-    if (!object->IsJSReceiver()) return value;
-    return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
-                                  value, language_mode);
+    return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value,
+                                                   attrs);
+  } else {
+    if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
+    return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
+                                                    attrs);
   }
-  return Object::SetProperty(object, name, value, language_mode);
 }
 
 
@@ -1269,27 +1355,23 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 4);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
 
-  uint32_t index = 0;
-  LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
-  LookupIterator it = name->AsArrayIndex(&index)
-                          ? LookupIterator(isolate, object, index, c)
-                          : LookupIterator(object, name, c);
-  if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
-    return isolate->heap()->undefined_value();
+  LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
+  if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) {
+    if (!isolate->MayAccess(js_object)) {
+      return isolate->heap()->undefined_value();
+    }
+    it.Next();
   }
 
   Handle<Object> result;
-  MaybeHandle<Object> maybe_result =
-      it.IsElement()
-          ? JSObject::SetOwnElementIgnoreAttributes(object, index, value, attrs)
-          : JSObject::SetOwnPropertyIgnoreAttributes(object, name, value,
-                                                     attrs);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      Runtime::DefineObjectProperty(js_object, name, obj_value, attrs));
   return *result;
 }
 
@@ -1299,8 +1381,8 @@ RUNTIME_FUNCTION(Runtime_GetDataProperty) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-  return *JSReceiver::GetDataProperty(object, name);
+  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
+  return *JSReceiver::GetDataProperty(object, key);
 }
 
 
index b855ca5ac949ceccef075d7db70f886ead930cf2..86502ee6ea4271049ebbd337303991c90e32bd1a 100644 (file)
@@ -822,6 +822,10 @@ class Runtime : public AllStatic {
       Isolate* isolate, Handle<Object> object, Handle<Object> key,
       Handle<Object> value, LanguageMode language_mode);
 
+  MUST_USE_RESULT static MaybeHandle<Object> DefineObjectProperty(
+      Handle<JSObject> object, Handle<Object> key, Handle<Object> value,
+      PropertyAttributes attr);
+
   MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
       Isolate* isolate, Handle<Object> object, Handle<Object> key);
 
index f91df650800cb432abdef22d98cc3b29d6b2e1a1..b819b172c4ad1db78926b0d59dc253d9841de94f 100644 (file)
@@ -505,12 +505,12 @@ FunctionKind ScopeInfo::function_kind() {
 }
 
 
-void ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
+bool ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
                                                Handle<Context> context,
                                                Handle<JSObject> scope_object) {
   Isolate* isolate = scope_info->GetIsolate();
   int local_count = scope_info->ContextLocalCount();
-  if (local_count == 0) return;
+  if (local_count == 0) return true;
   // Fill all context locals to the context extension.
   int first_context_var = scope_info->StackLocalCount();
   int start = scope_info->ContextLocalNameEntriesIndex();
@@ -520,12 +520,14 @@ void ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
     Handle<Object> value = Handle<Object>(context->get(context_index), isolate);
     // Reflect variables under TDZ as undefined in scope object.
     if (value->IsTheHole()) continue;
-    // This should always succeed.
-    // TODO(verwaest): Use AddDataProperty instead.
-    JSObject::SetOwnPropertyIgnoreAttributes(
-        scope_object, handle(String::cast(scope_info->get(i + start))), value,
-        ::NONE).Check();
+    RETURN_ON_EXCEPTION_VALUE(
+        isolate, Runtime::DefineObjectProperty(
+                     scope_object,
+                     Handle<String>(String::cast(scope_info->get(i + start))),
+                     value, ::NONE),
+        false);
   }
+  return true;
 }
 
 
index 25a75103e3704e5f7938877b8d56fee2ea9b2ffc..59b2bad9ca2037c3f1c78f2176836e2a5d2f4766 100644 (file)
@@ -115,9 +115,8 @@ class DebugLocalContext {
         v8::Utils::OpenHandle(*context_->Global())));
     Handle<v8::internal::String> debug_string =
         factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug"));
-    v8::internal::JSObject::SetOwnPropertyIgnoreAttributes(
-        global, debug_string, handle(debug_context->global_proxy()), DONT_ENUM)
-        .Check();
+    v8::internal::Runtime::DefineObjectProperty(global, debug_string,
+        handle(debug_context->global_proxy(), isolate), DONT_ENUM).Check();
   }
 
  private: