Index: src/execution.cc |
diff --git a/src/execution.cc b/src/execution.cc |
index bdbdca81bb7cfcdf5cf34316ce4d541abab5fed6..cdea005829fb4e1fec14d4402272592cb58138d5 100644 |
--- a/src/execution.cc |
+++ b/src/execution.cc |
@@ -149,12 +149,28 @@ Handle<Object> Execution::Call(Handle<Object> callable, |
Handle<Object> receiver, |
int argc, |
Object*** args, |
- bool* pending_exception) { |
+ bool* pending_exception, |
+ bool convert_receiver) { |
if (!callable->IsJSFunction()) { |
callable = TryGetFunctionDelegate(callable, pending_exception); |
if (*pending_exception) return callable; |
} |
Handle<JSFunction> func = Handle<JSFunction>::cast(callable); |
+ |
+ // In non-strict mode, convert receiver. |
+ if (convert_receiver && !receiver->IsJSReceiver() && |
+ !func->shared()->native() && !func->shared()->strict_mode()) { |
+ if (receiver->IsUndefined() || receiver->IsNull()) { |
+ // Careful, func->context()->global()->global_receiver() gives |
+ // the JSBuiltinsObject if func is a builtin. Not what we want here. |
+ receiver = |
+ Handle<Object>(func->GetIsolate()->global()->global_receiver()); |
+ } else { |
+ receiver = ToObject(receiver, pending_exception); |
+ } |
+ if (*pending_exception) return callable; |
+ } |
+ |
return Invoke(false, func, receiver, argc, args, pending_exception); |
} |
@@ -210,10 +226,17 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { |
// If you return a function from here, it will be called when an |
// attempt is made to call the given object as a function. |
+ // If object is a function proxies, get its handler. Iterate if necessary. |
+ Object* fun = *object; |
+ while (fun->IsJSFunctionProxy()) { |
+ fun = JSFunctionProxy::cast(fun)->call_trap(); |
+ } |
+ if (fun->IsJSFunction()) return Handle<Object>(fun); |
+ |
// Objects created through the API can have an instance-call handler |
// that should be used when calling the object as a function. |
- if (object->IsHeapObject() && |
- HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
+ if (fun->IsHeapObject() && |
+ HeapObject::cast(fun)->map()->has_instance_call_handler()) { |
return Handle<JSFunction>( |
isolate->global_context()->call_as_function_delegate()); |
} |
@@ -227,10 +250,17 @@ Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, |
ASSERT(!object->IsJSFunction()); |
Isolate* isolate = Isolate::Current(); |
+ // If object is a function proxies, get its handler. Iterate if necessary. |
+ Object* fun = *object; |
+ while (fun->IsJSFunctionProxy()) { |
+ fun = JSFunctionProxy::cast(fun)->call_trap(); |
+ } |
+ if (fun->IsJSFunction()) return Handle<Object>(fun); |
+ |
// Objects created through the API can have an instance-call handler |
// that should be used when calling the object as a function. |
- if (object->IsHeapObject() && |
- HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
+ if (fun->IsHeapObject() && |
+ HeapObject::cast(fun)->map()->has_instance_call_handler()) { |
return Handle<JSFunction>( |
isolate->global_context()->call_as_function_delegate()); |
} |
@@ -253,10 +283,17 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { |
// If you return a function from here, it will be called when an |
// attempt is made to call the given object as a constructor. |
+ // If object is a function proxies, get its handler. Iterate if necessary. |
+ Object* fun = *object; |
+ while (fun->IsJSFunctionProxy()) { |
+ fun = JSFunctionProxy::cast(fun)->call_trap(); |
+ } |
+ if (fun->IsJSFunction()) return Handle<Object>(fun); |
+ |
// Objects created through the API can have an instance-call handler |
// that should be used when calling the object as a function. |
- if (object->IsHeapObject() && |
- HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
+ if (fun->IsHeapObject() && |
+ HeapObject::cast(fun)->map()->has_instance_call_handler()) { |
return Handle<JSFunction>( |
isolate->global_context()->call_as_constructor_delegate()); |
} |
@@ -274,10 +311,17 @@ Handle<Object> Execution::TryGetConstructorDelegate( |
// If you return a function from here, it will be called when an |
// attempt is made to call the given object as a constructor. |
+ // If object is a function proxies, get its handler. Iterate if necessary. |
+ Object* fun = *object; |
+ while (fun->IsJSFunctionProxy()) { |
+ fun = JSFunctionProxy::cast(fun)->call_trap(); |
+ } |
+ if (fun->IsJSFunction()) return Handle<Object>(fun); |
+ |
// Objects created through the API can have an instance-call handler |
// that should be used when calling the object as a function. |
- if (object->IsHeapObject() && |
- HeapObject::cast(*object)->map()->has_instance_call_handler()) { |
+ if (fun->IsHeapObject() && |
+ HeapObject::cast(fun)->map()->has_instance_call_handler()) { |
return Handle<JSFunction>( |
isolate->global_context()->call_as_constructor_delegate()); |
} |
@@ -553,7 +597,7 @@ Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) { |
Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) { |
- if (obj->IsJSObject()) return obj; |
+ if (obj->IsSpecObject()) return obj; |
RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc); |
} |