Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index d910c01101d3879a015f211492d66a4dc1e8af3f..d84d561768fa6200af9d270752b27c8559304d59 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -4476,11 +4476,13 @@ BUILTIN(RestrictedStrictArgumentsPropertiesThrower) { |
namespace { |
-template <bool is_construct> |
MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( |
- Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) { |
+ Isolate* isolate, |
+ BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args) { |
HandleScope scope(isolate); |
Handle<HeapObject> function = args.target<HeapObject>(); |
+ Handle<HeapObject> new_target = args.new_target(); |
+ bool is_construct = !new_target->IsUndefined(); |
Handle<JSReceiver> receiver; |
DCHECK(function->IsFunctionTemplateInfo() || |
@@ -4540,13 +4542,9 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( |
LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
DCHECK(raw_holder->IsJSObject()); |
- FunctionCallbackArguments custom(isolate, |
- data_obj, |
- *function, |
- raw_holder, |
- &args[0] - 1, |
- args.length() - 1, |
- is_construct); |
+ FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder, |
+ *new_target, &args[0] - 1, |
+ args.length() - 1); |
Handle<Object> result = custom.Call(callback); |
if (result.is_null()) result = isolate->factory()->undefined_value(); |
@@ -4567,19 +4565,11 @@ BUILTIN(HandleApiCall) { |
HandleScope scope(isolate); |
Handle<Object> result; |
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
- HandleApiCallHelper<false>(isolate, args)); |
+ HandleApiCallHelper(isolate, args)); |
return *result; |
} |
-BUILTIN(HandleApiCallConstruct) { |
- HandleScope scope(isolate); |
- Handle<Object> result; |
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
- HandleApiCallHelper<true>(isolate, args)); |
- return *result; |
-} |
- |
Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode, |
TailCallMode tail_call_mode) { |
switch (tail_call_mode) { |
@@ -4661,11 +4651,12 @@ Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) { |
namespace { |
class RelocatableArguments |
- : public BuiltinArguments<BuiltinExtraArguments::kTarget>, |
+ : public BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>, |
public Relocatable { |
public: |
RelocatableArguments(Isolate* isolate, int length, Object** arguments) |
- : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments), |
+ : BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>(length, |
+ arguments), |
Relocatable(isolate) {} |
virtual inline void IterateInstance(ObjectVisitor* v) { |
@@ -4697,24 +4688,26 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function, |
} |
} |
} |
- // Construct BuiltinArguments object: function, arguments reversed, receiver. |
+ // Construct BuiltinArguments object: |
+ // new target, function, arguments reversed, receiver. |
const int kBufferSize = 32; |
Object* small_argv[kBufferSize]; |
Object** argv; |
- if (argc + 2 <= kBufferSize) { |
+ if (argc + 3 <= kBufferSize) { |
argv = small_argv; |
} else { |
- argv = new Object* [argc + 2]; |
+ argv = new Object*[argc + 3]; |
} |
- argv[argc + 1] = *receiver; |
+ argv[argc + 2] = *receiver; |
for (int i = 0; i < argc; ++i) { |
- argv[argc - i] = *args[i]; |
+ argv[argc - i + 1] = *args[i]; |
} |
- argv[0] = *function; |
+ argv[1] = *function; |
+ argv[0] = isolate->heap()->undefined_value(); // new target |
MaybeHandle<Object> result; |
{ |
- RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]); |
- result = HandleApiCallHelper<false>(isolate, arguments); |
+ RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2); |
+ result = HandleApiCallHelper(isolate, arguments); |
} |
if (argv != small_argv) { |
delete[] argv; |
@@ -4734,6 +4727,18 @@ MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( |
// Get the object called. |
JSObject* obj = JSObject::cast(*receiver); |
+ // Set the new target. |
+ HeapObject* new_target; |
+ if (is_construct_call) { |
+ // TODO(adamk): This should be passed through in args instead of |
+ // being patched in here. We need to set a non-undefined value |
+ // for v8::FunctionCallbackInfo::IsConstructCall() to get the |
+ // right answer. |
+ new_target = obj; |
+ } else { |
+ new_target = isolate->heap()->undefined_value(); |
+ } |
+ |
// Get the invocation callback from the function descriptor that was |
// used to create the called object. |
DCHECK(obj->map()->is_callable()); |
@@ -4756,13 +4761,9 @@ MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( |
HandleScope scope(isolate); |
LOG(isolate, ApiObjectAccess("call non-function", obj)); |
- FunctionCallbackArguments custom(isolate, |
- call_data->data(), |
- constructor, |
- obj, |
- &args[0] - 1, |
- args.length() - 1, |
- is_construct_call); |
+ FunctionCallbackArguments custom(isolate, call_data->data(), constructor, |
+ obj, new_target, &args[0] - 1, |
+ args.length() - 1); |
Handle<Object> result_handle = custom.Call(callback); |
if (result_handle.is_null()) { |
result = isolate->heap()->undefined_value(); |