| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 6703)
|
| +++ src/runtime.cc (working copy)
|
| @@ -884,10 +884,17 @@
|
| return obj->PreventExtensions();
|
| }
|
|
|
| +
|
| static MaybeObject* Runtime_IsExtensible(Arguments args) {
|
| ASSERT(args.length() == 1);
|
| CONVERT_CHECKED(JSObject, obj, args[0]);
|
| - return obj->map()->is_extensible() ? Heap::true_value()
|
| + if (obj->IsJSGlobalProxy()) {
|
| + Object* proto = obj->GetPrototype();
|
| + if (proto->IsNull()) return Heap::false_value();
|
| + ASSERT(proto->IsJSGlobalObject());
|
| + obj = JSObject::cast(proto);
|
| + }
|
| + return obj->map()->is_extensible() ? Heap::true_value()
|
| : Heap::false_value();
|
| }
|
|
|
| @@ -1082,7 +1089,11 @@
|
| const char* type = (lookup.IsReadOnly()) ? "const" : "var";
|
| return ThrowRedeclarationError(type, name);
|
| }
|
| - SetProperty(global, name, value, attributes);
|
| + Handle<Object> result = SetProperty(global, name, value, attributes);
|
| + if (result.is_null()) {
|
| + ASSERT(Top::has_pending_exception());
|
| + return Failure::Exception();
|
| + }
|
| } else {
|
| // If a property with this name does not already exist on the
|
| // global object add the property locally. We take special
|
| @@ -1090,10 +1101,16 @@
|
| // of callbacks in the prototype chain (this rules out using
|
| // SetProperty). Also, we must use the handle-based version to
|
| // avoid GC issues.
|
| - SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
|
| + Handle<Object> result =
|
| + SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
|
| + if (result.is_null()) {
|
| + ASSERT(Top::has_pending_exception());
|
| + return Failure::Exception();
|
| + }
|
| }
|
| }
|
|
|
| + ASSERT(!Top::has_pending_exception());
|
| return Heap::undefined_value();
|
| }
|
|
|
| @@ -1143,12 +1160,15 @@
|
| } else {
|
| // The holder is an arguments object.
|
| Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
|
| - SetElement(arguments, index, initial_value);
|
| + Handle<Object> result = SetElement(arguments, index, initial_value);
|
| + if (result.is_null()) return Failure::Exception();
|
| }
|
| } else {
|
| // Slow case: The property is not in the FixedArray part of the context.
|
| Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
|
| - SetProperty(context_ext, name, initial_value, mode);
|
| + Handle<Object> result =
|
| + SetProperty(context_ext, name, initial_value, mode);
|
| + if (result.is_null()) return Failure::Exception();
|
| }
|
| }
|
|
|
| @@ -1175,8 +1195,8 @@
|
| ASSERT(!context_ext->HasLocalProperty(*name));
|
| Handle<Object> value(Heap::undefined_value());
|
| if (*initial_value != NULL) value = initial_value;
|
| - SetProperty(context_ext, name, value, mode);
|
| - ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
|
| + Handle<Object> result = SetProperty(context_ext, name, value, mode);
|
| + if (result.is_null()) return Failure::Exception();
|
| }
|
|
|
| return Heap::undefined_value();
|
| @@ -3668,14 +3688,20 @@
|
| if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) &&
|
| is_element) {
|
| // Normalize the elements to enable attributes on the property.
|
| - if (!js_object->IsJSGlobalProxy()) {
|
| - NormalizeElements(js_object);
|
| + if (js_object->IsJSGlobalProxy()) {
|
| + Handle<Object> proto(js_object->GetPrototype());
|
| + // If proxy is detached, ignore the assignment. Alternatively,
|
| + // we could throw an exception.
|
| + if (proto->IsNull()) return *obj_value;
|
| + js_object = Handle<JSObject>::cast(proto);
|
| }
|
| + NormalizeElements(js_object);
|
| Handle<NumberDictionary> dictionary(js_object->element_dictionary());
|
| // Make sure that we never go back to fast case.
|
| dictionary->set_requires_slow_elements();
|
| PropertyDetails details = PropertyDetails(attr, NORMAL);
|
| NumberDictionarySet(dictionary, index, obj_value, details);
|
| + return *obj_value;
|
| }
|
|
|
| LookupResult result;
|
| @@ -3690,9 +3716,12 @@
|
| if (result.IsProperty() &&
|
| (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
|
| // New attributes - normalize to avoid writing to instance descriptor
|
| - if (!js_object->IsJSGlobalProxy()) {
|
| - NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| + if (js_object->IsJSGlobalProxy()) {
|
| + // Since the result is a property, the prototype will exist so
|
| + // we don't have to check for null.
|
| + js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
|
| }
|
| + NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| // Use IgnoreAttributes version since a readonly property may be
|
| // overridden and SetProperty does not allow this.
|
| return js_object->SetLocalPropertyIgnoreAttributes(*name,
|
| @@ -6681,28 +6710,50 @@
|
| return *result;
|
| }
|
|
|
| +
|
| static MaybeObject* Runtime_NewObjectFromBound(Arguments args) {
|
| HandleScope scope;
|
| ASSERT(args.length() == 2);
|
| + // First argument is a function to use as a constructor.
|
| CONVERT_ARG_CHECKED(JSFunction, function, 0);
|
| - CONVERT_ARG_CHECKED(JSArray, params, 1);
|
|
|
| - RUNTIME_ASSERT(params->HasFastElements());
|
| - FixedArray* fixed = FixedArray::cast(params->elements());
|
| + // Second argument is either null or an array of bound arguments.
|
| + FixedArray* bound_args = NULL;
|
| + int bound_argc = 0;
|
| + if (!args[1]->IsNull()) {
|
| + CONVERT_ARG_CHECKED(JSArray, params, 1);
|
| + RUNTIME_ASSERT(params->HasFastElements());
|
| + bound_args = FixedArray::cast(params->elements());
|
| + bound_argc = Smi::cast(params->length())->value();
|
| + }
|
|
|
| - int fixed_length = Smi::cast(params->length())->value();
|
| - SmartPointer<Object**> param_data(NewArray<Object**>(fixed_length));
|
| - for (int i = 0; i < fixed_length; i++) {
|
| - Handle<Object> val = Handle<Object>(fixed->get(i));
|
| + // Find frame containing arguments passed to the caller.
|
| + JavaScriptFrameIterator it;
|
| + JavaScriptFrame* frame = it.frame();
|
| + ASSERT(!frame->is_optimized());
|
| + it.AdvanceToArgumentsFrame();
|
| + frame = it.frame();
|
| + int argc = frame->GetProvidedParametersCount();
|
| +
|
| + // Prepend bound arguments to caller's arguments.
|
| + int total_argc = bound_argc + argc;
|
| + SmartPointer<Object**> param_data(NewArray<Object**>(total_argc));
|
| + for (int i = 0; i < bound_argc; i++) {
|
| + Handle<Object> val = Handle<Object>(bound_args->get(i));
|
| param_data[i] = val.location();
|
| }
|
| + for (int i = 0; i < argc; i++) {
|
| + Handle<Object> val = Handle<Object>(frame->GetParameter(i));
|
| + param_data[bound_argc + i] = val.location();
|
| + }
|
|
|
| bool exception = false;
|
| - Handle<Object> result = Execution::New(
|
| - function, fixed_length, *param_data, &exception);
|
| + Handle<Object> result =
|
| + Execution::New(function, total_argc, *param_data, &exception);
|
| if (exception) {
|
| return Failure::Exception();
|
| }
|
| +
|
| ASSERT(!result.is_null());
|
| return *result;
|
| }
|
| @@ -7340,12 +7391,17 @@
|
| if (holder->IsContext()) {
|
| // Ignore if read_only variable.
|
| if ((attributes & READ_ONLY) == 0) {
|
| - Handle<Context>::cast(holder)->set(index, *value);
|
| + // Context is a fixed array and set cannot fail.
|
| + Context::cast(*holder)->set(index, *value);
|
| }
|
| } else {
|
| ASSERT((attributes & READ_ONLY) == 0);
|
| - Handle<JSObject>::cast(holder)->SetElement(index, *value)->
|
| - ToObjectUnchecked();
|
| + Handle<Object> result =
|
| + SetElement(Handle<JSObject>::cast(holder), index, value);
|
| + if (result.is_null()) {
|
| + ASSERT(Top::has_pending_exception());
|
| + return Failure::Exception();
|
| + }
|
| }
|
| return *value;
|
| }
|
| @@ -7368,8 +7424,8 @@
|
| // extension object itself.
|
| if ((attributes & READ_ONLY) == 0 ||
|
| (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
|
| - Handle<Object> set = SetProperty(context_ext, name, value, NONE);
|
| - if (set.is_null()) {
|
| + Handle<Object> result = SetProperty(context_ext, name, value, NONE);
|
| + if (result.is_null()) {
|
| // Failure::Exception is converted to a null handle in the
|
| // handle-based methods such as SetProperty. We therefore need
|
| // to convert null handles back to exceptions.
|
|
|