Fix some bugs in Function.prototype.bind implementation.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Jul 2010 09:20:21 +0000 (09:20 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Jul 2010 09:20:21 +0000 (09:20 +0000)
Correctly handle not passing thisArg.
Fixes to NewObjectFromBound to use correct argument count, not leak memory,
and handle constructors that throw exceptions.

Review URL: http://codereview.chromium.org/2878057

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5137 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
src/v8natives.js

index a6924a0..4063a0f 100644 (file)
@@ -6757,17 +6757,23 @@ static Object* Runtime_NewObjectFromBound(Arguments args) {
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   CONVERT_ARG_CHECKED(JSArray, params, 1);
 
+  RUNTIME_ASSERT(params->HasFastElements());
   FixedArray* fixed = FixedArray::cast(params->elements());
 
-  bool exception = false;
-  Object*** param_data = NewArray<Object**>(fixed->length());
-  for (int i = 0; i < fixed->length();  i++) {
+  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));
     param_data[i] = val.location();
   }
 
+  bool exception = false;
   Handle<Object> result = Execution::New(
-      function, fixed->length(), param_data, &exception);
+      function, fixed_length, *param_data, &exception);
+  if (exception) {
+      return Failure::Exception();
+  }
+  ASSERT(!result.is_null());
   return *result;
 }
 
index 18e56c3..6eb1371 100644 (file)
@@ -1105,7 +1105,7 @@ function FunctionBind(this_arg) { // Length is 1.
       throw new $TypeError('Bind must be called on a function');
   }
   // this_arg is not an argument that should be bound.
-  var argc_bound = %_ArgumentsLength() - 1;
+  var argc_bound = (%_ArgumentsLength() || 1) - 1;
   if (argc_bound > 0) {
     var bound_args = new $Array(argc_bound);
     for(var i = 0; i < argc_bound; i++) {