diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index baf6728167..e974c232a1 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -181,7 +181,7 @@ Value NewExpression::execute(Interpreter& interpreter, GlobalObject& global_obje if (vm.exception()) return {}; - if (!callee_value.is_function() || (is(callee_value.as_object()) && !static_cast(callee_value.as_object()).has_constructor())) { + if (!callee_value.is_function() || !callee_value.as_function().has_constructor()) { throw_type_error_for_callee(interpreter, global_object, callee_value, "constructor"sv); return {}; } diff --git a/Userland/Libraries/LibJS/Runtime/BoundFunction.h b/Userland/Libraries/LibJS/Runtime/BoundFunction.h index af16ceff65..0b83c78ad6 100644 --- a/Userland/Libraries/LibJS/Runtime/BoundFunction.h +++ b/Userland/Libraries/LibJS/Runtime/BoundFunction.h @@ -23,6 +23,7 @@ public: virtual FunctionEnvironment* create_environment(FunctionObject&) override; virtual const FlyString& name() const override { return m_name; } virtual bool is_strict_mode() const override { return m_bound_target_function->is_strict_mode(); } + virtual bool has_constructor() const override { return true; } FunctionObject& bound_target_function() const { return *m_bound_target_function; } Value bound_this() const { return m_bound_this; } diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h index 37d1ae4957..f88837dad7 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h @@ -71,6 +71,8 @@ public: // This is for IsSimpleParameterList (static semantics) bool has_simple_parameter_list() const { return m_has_simple_parameter_list; } + virtual bool has_constructor() const override { return true; } + protected: virtual bool is_strict_mode() const final { return m_strict; } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionObject.h b/Userland/Libraries/LibJS/Runtime/FunctionObject.h index 7f3251e0f3..4b898e3795 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionObject.h +++ b/Userland/Libraries/LibJS/Runtime/FunctionObject.h @@ -27,6 +27,8 @@ public: virtual bool is_strict_mode() const { return false; } + virtual bool has_constructor() const { return false; } + // [[Realm]] virtual Realm* realm() const { return nullptr; } diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.h b/Userland/Libraries/LibJS/Runtime/NativeFunction.h index e84b4ef1fc..d42b156144 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.h @@ -23,12 +23,9 @@ public: virtual Value call() override; virtual Value construct(FunctionObject& new_target) override; - virtual const FlyString& name() const override { return m_name; }; - virtual bool has_constructor() const { return false; } - virtual bool is_strict_mode() const override; - + virtual bool has_constructor() const override { return false; } virtual Realm* realm() const override { return m_realm; } protected: diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.h b/Userland/Libraries/LibJS/Runtime/ProxyObject.h index d96b5f2822..0a2397c80c 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.h +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.h @@ -24,6 +24,7 @@ public: virtual Value construct(FunctionObject& new_target) override; virtual const FlyString& name() const override; virtual FunctionEnvironment* create_environment(FunctionObject&) override; + virtual bool has_constructor() const override { return true; } const Object& target() const { return m_target; } const Object& handler() const { return m_handler; } diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 9e9d099e87..6644c2d4be 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -237,14 +237,16 @@ FunctionObject const& Value::as_function() const // 7.2.4 IsConstructor ( argument ), https://tc39.es/ecma262/#sec-isconstructor bool Value::is_constructor() const { + // 1. If Type(argument) is not Object, return false. if (!is_function()) return false; - if (is(as_object())) - return static_cast(as_object()).has_constructor(); - if (is(as_object())) - return Value(&static_cast(as_object()).bound_target_function()).is_constructor(); - // ECMAScriptFunctionObject - return true; + + // 2. If argument has a [[Construct]] internal method, return true. + if (as_function().has_constructor()) + return true; + + // 3. Return false. + return false; } // 7.2.8 IsRegExp ( argument ), https://tc39.es/ecma262/#sec-isregexp