Commit b478e9c1 authored by vabr's avatar vabr Committed by Commit bot

Fix TypeError message for Reflect.construct

If the Reflect.construct receives an argument expected to be a constructor,
and the argument is not a constructor, V8 currently declares that
Reflect.construct is not a function. It should instead say that the offending
argument is not a constructor.

This is the case for all ports of builtins
(Builtins::Generate_ReflectConstruct). All of them make an
attempt to at least pass the right argument to the TypeError parametrised
message, calling out the offending Reflect.construct argument. However,
Runtime::kThrowCalledNonCallable extracts the callsite from those arguments,
discarding the precise information.

This CL adds Runtime::kNotConstructor, which reports the arguments passed
to it, and the CL also modifies the ports of builtins to make use of
Runtime::kNotConstructor

BUG=v8:5671

Review-Url: https://codereview.chromium.org/2688393003
Cr-Commit-Position: refs/heads/master@{#43182}
parent 296553bf
...@@ -2093,14 +2093,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2093,14 +2093,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ str(r1, MemOperand(sp, 0)); __ str(r1, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ str(r3, MemOperand(sp, 0)); __ str(r3, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -2148,14 +2148,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2148,14 +2148,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ Bind(&target_not_constructor); __ Bind(&target_not_constructor);
{ {
__ Poke(target, 0); __ Poke(target, 0);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ Bind(&new_target_not_constructor); __ Bind(&new_target_not_constructor);
{ {
__ Poke(new_target, 0); __ Poke(new_target, 0);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -1650,14 +1650,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -1650,14 +1650,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ mov(Operand(esp, kPointerSize), edi); __ mov(Operand(esp, kPointerSize), edi);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ mov(Operand(esp, kPointerSize), edx); __ mov(Operand(esp, kPointerSize), edx);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -2120,14 +2120,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2120,14 +2120,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ sw(a1, MemOperand(sp)); __ sw(a1, MemOperand(sp));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ sw(a3, MemOperand(sp)); __ sw(a3, MemOperand(sp));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -2124,14 +2124,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2124,14 +2124,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ sd(target, MemOperand(sp)); __ sd(target, MemOperand(sp));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ sd(new_target, MemOperand(sp)); __ sd(new_target, MemOperand(sp));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -2144,14 +2144,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2144,14 +2144,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ StoreP(r4, MemOperand(sp, 0)); __ StoreP(r4, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ StoreP(r6, MemOperand(sp, 0)); __ StoreP(r6, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -2148,14 +2148,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2148,14 +2148,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ StoreP(r3, MemOperand(sp, 0)); __ StoreP(r3, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ StoreP(r5, MemOperand(sp, 0)); __ StoreP(r5, MemOperand(sp, 0));
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -1610,7 +1610,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -1610,7 +1610,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
{ {
StackArgumentsAccessor args(rsp, 0); StackArgumentsAccessor args(rsp, 0);
__ movp(args.GetReceiverOperand(), rdi); __ movp(args.GetReceiverOperand(), rdi);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
...@@ -1618,7 +1618,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -1618,7 +1618,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
{ {
StackArgumentsAccessor args(rsp, 0); StackArgumentsAccessor args(rsp, 0);
__ movp(args.GetReceiverOperand(), rdx); __ movp(args.GetReceiverOperand(), rdx);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -1617,14 +1617,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -1617,14 +1617,14 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
{ {
__ mov(Operand(esp, kPointerSize), edi); __ mov(Operand(esp, kPointerSize), edi);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
// 4c. The new.target is not a constructor, throw an appropriate TypeError. // 4c. The new.target is not a constructor, throw an appropriate TypeError.
__ bind(&new_target_not_constructor); __ bind(&new_target_not_constructor);
{ {
__ mov(Operand(esp, kPointerSize), edx); __ mov(Operand(esp, kPointerSize), edx);
__ TailCallRuntime(Runtime::kThrowCalledNonCallable); __ TailCallRuntime(Runtime::kThrowNotConstructor);
} }
} }
......
...@@ -237,6 +237,14 @@ RUNTIME_FUNCTION(Runtime_ThrowNonObjectInInstanceOfCheck) { ...@@ -237,6 +237,14 @@ RUNTIME_FUNCTION(Runtime_ThrowNonObjectInInstanceOfCheck) {
isolate, NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck)); isolate, NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck));
} }
RUNTIME_FUNCTION(Runtime_ThrowNotConstructor) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotConstructor, object));
}
RUNTIME_FUNCTION(Runtime_ThrowNotGeneric) { RUNTIME_FUNCTION(Runtime_ThrowNotGeneric) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
...@@ -378,7 +386,6 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) { ...@@ -378,7 +386,6 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) {
} // namespace } // namespace
RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) { RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
......
...@@ -321,6 +321,7 @@ namespace internal { ...@@ -321,6 +321,7 @@ namespace internal {
F(ThrowSymbolIteratorInvalid, 0, 1) \ F(ThrowSymbolIteratorInvalid, 0, 1) \
F(ThrowNonCallableInInstanceOfCheck, 0, 1) \ F(ThrowNonCallableInInstanceOfCheck, 0, 1) \
F(ThrowNonObjectInInstanceOfCheck, 0, 1) \ F(ThrowNonObjectInInstanceOfCheck, 0, 1) \
F(ThrowNotConstructor, 1, 1) \
F(ThrowNotGeneric, 1, 1) \ F(ThrowNotGeneric, 1, 1) \
F(ThrowReferenceError, 1, 1) \ F(ThrowReferenceError, 1, 1) \
F(ThrowStackOverflow, 0, 1) \ F(ThrowStackOverflow, 0, 1) \
......
...@@ -17,6 +17,30 @@ ...@@ -17,6 +17,30 @@
})(); })();
(function testReflectConstructArg1NonConstructor() {
try {
Reflect.construct(() => {}, []);
} catch (e) {
assertInstanceof(e, TypeError);
assertEquals("() => {} is not a constructor", e.message);
return;
}
assertUnreachable("Exception expected");
})();
(function testReflectConstructArg3NonConstructor() {
try {
Reflect.construct(function() {}, [], () => {});
} catch (e) {
assertInstanceof(e, TypeError);
assertEquals("() => {} is not a constructor", e.message);
return;
}
assertUnreachable("Exception expected");
})();
(function testReflectConstructBasic() { (function testReflectConstructBasic() {
function Constructor() { "use strict"; } function Constructor() { "use strict"; }
assertInstanceof(Reflect.construct(Constructor, []), Constructor); assertInstanceof(Reflect.construct(Constructor, []), Constructor);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment