From 38157a60936f2c8718e1ae9b1bc664db1c832931 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 25 Sep 2021 09:52:49 +0200 Subject: [PATCH] LibJS: Move has_constructor() from NativeFunction to FunctionObject At a later point this will indicate whether some FunctionObject "has a [[Construct]] internal method" (separate from the current FunctionObject call() / construct()), to help with a more spec-compliant implementation of [[Call]] and [[Construct]]. This means that it is no longer relevant to just NativeFunction. --- Userland/Libraries/LibJS/AST.cpp | 2 +- Userland/Libraries/LibJS/Runtime/BoundFunction.h | 1 + .../LibJS/Runtime/ECMAScriptFunctionObject.h | 2 ++ Userland/Libraries/LibJS/Runtime/FunctionObject.h | 2 ++ Userland/Libraries/LibJS/Runtime/NativeFunction.h | 5 +---- Userland/Libraries/LibJS/Runtime/ProxyObject.h | 1 + Userland/Libraries/LibJS/Runtime/Value.cpp | 14 ++++++++------ 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index baf67281674..e974c232a16 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 af16ceff65a..0b83c78ad6d 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 37d1ae4957d..f88837dad76 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 7f3251e0f3b..4b898e37956 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 e84b4ef1fcb..d42b1561441 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 d96b5f28220..0a2397c80c0 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 9e9d099e871..6644c2d4be9 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