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. |