LibJS: Remove unnecessary FunctionObject::name() virtual

This allows us to remove the BoundFunction::m_name field, which we
were initializing with a formatted FlyString on every function binding,
despite never using it for anything.
This commit is contained in:
Andreas Kling 2025-04-09 22:31:12 +02:00 committed by Alexander Kalenik
commit 4a5863bcdb
Notes: github-actions[bot] 2025-04-10 02:01:55 +00:00
11 changed files with 5 additions and 26 deletions

View file

@ -69,7 +69,7 @@ static void update_function_name(Value value, FlyString const& name)
if (!value.is_function()) if (!value.is_function())
return; return;
auto& function = value.as_function(); auto& function = value.as_function();
if (is<ECMAScriptFunctionObject>(function) && function.name().is_empty()) if (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject const&>(function).name().is_empty())
static_cast<ECMAScriptFunctionObject&>(function).set_name(name); static_cast<ECMAScriptFunctionObject&>(function).set_name(name);
} }

View file

@ -1212,14 +1212,14 @@ inline ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value thi
switch (kind) { switch (kind) {
case Op::PropertyKind::Getter: { case Op::PropertyKind::Getter: {
auto& function = value.as_function(); auto& function = value.as_function();
if (function.name().is_empty() && is<ECMAScriptFunctionObject>(function)) if (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject const&>(function).name().is_empty())
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("get {}", name))); static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("get {}", name)));
object->define_direct_accessor(name, &function, nullptr, Attribute::Configurable | Attribute::Enumerable); object->define_direct_accessor(name, &function, nullptr, Attribute::Configurable | Attribute::Enumerable);
break; break;
} }
case Op::PropertyKind::Setter: { case Op::PropertyKind::Setter: {
auto& function = value.as_function(); auto& function = value.as_function();
if (function.name().is_empty() && is<ECMAScriptFunctionObject>(function)) if (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject const&>(function).name().is_empty())
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("set {}", name))); static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("set {}", name)));
object->define_direct_accessor(name, nullptr, &function, Attribute::Configurable | Attribute::Enumerable); object->define_direct_accessor(name, nullptr, &function, Attribute::Configurable | Attribute::Enumerable);
break; break;

View file

@ -39,8 +39,6 @@ BoundFunction::BoundFunction(Realm& realm, FunctionObject& bound_target_function
, m_bound_target_function(&bound_target_function) , m_bound_target_function(&bound_target_function)
, m_bound_this(bound_this) , m_bound_this(bound_this)
, m_bound_arguments(move(bound_arguments)) , m_bound_arguments(move(bound_arguments))
// FIXME: Non-standard and redundant, remove.
, m_name(MUST(String::formatted("bound {}", bound_target_function.name())))
{ {
} }

View file

@ -23,7 +23,6 @@ public:
virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override; virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override; virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override;
virtual FlyString const& name() const override { return m_name; }
virtual bool is_strict_mode() const override { return m_bound_target_function->is_strict_mode(); } virtual bool is_strict_mode() const override { return m_bound_target_function->is_strict_mode(); }
virtual bool has_constructor() const override { return m_bound_target_function->has_constructor(); } virtual bool has_constructor() const override { return m_bound_target_function->has_constructor(); }
@ -39,8 +38,6 @@ private:
GC::Ptr<FunctionObject> m_bound_target_function; // [[BoundTargetFunction]] GC::Ptr<FunctionObject> m_bound_target_function; // [[BoundTargetFunction]]
Value m_bound_this; // [[BoundThis]] Value m_bound_this; // [[BoundThis]]
Vector<Value> m_bound_arguments; // [[BoundArguments]] Vector<Value> m_bound_arguments; // [[BoundArguments]]
FlyString m_name;
}; };
} }

View file

@ -127,7 +127,7 @@ public:
Statement const& ecmascript_code() const { return *shared_data().m_ecmascript_code; } Statement const& ecmascript_code() const { return *shared_data().m_ecmascript_code; }
[[nodiscard]] virtual FunctionParameters const& formal_parameters() const override { return *shared_data().m_formal_parameters; } [[nodiscard]] virtual FunctionParameters const& formal_parameters() const override { return *shared_data().m_formal_parameters; }
virtual FlyString const& name() const override { return shared_data().m_name; } FlyString const& name() const { return shared_data().m_name; }
void set_name(FlyString const& name); void set_name(FlyString const& name);
void set_is_class_constructor() { const_cast<SharedFunctionInstanceData&>(shared_data()).m_is_class_constructor = true; } void set_is_class_constructor() { const_cast<SharedFunctionInstanceData&>(shared_data()).m_is_class_constructor = true; }

View file

@ -26,8 +26,6 @@ public:
virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) = 0; virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) = 0;
virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct([[maybe_unused]] ReadonlySpan<Value> arguments_list, [[maybe_unused]] FunctionObject& new_target) { VERIFY_NOT_REACHED(); } virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct([[maybe_unused]] ReadonlySpan<Value> arguments_list, [[maybe_unused]] FunctionObject& new_target) { VERIFY_NOT_REACHED(); }
virtual FlyString const& name() const = 0;
void set_function_name(Variant<PropertyKey, PrivateName> const& name_arg, Optional<StringView> const& prefix = {}); void set_function_name(Variant<PropertyKey, PrivateName> const& name_arg, Optional<StringView> const& prefix = {});
void set_function_length(double length); void set_function_length(double length);

View file

@ -19,7 +19,6 @@ public:
virtual ~FunctionPrototype() override = default; virtual ~FunctionPrototype() override = default;
virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override; virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
virtual FlyString const& name() const override { return m_name; }
private: private:
explicit FunctionPrototype(Realm&); explicit FunctionPrototype(Realm&);
@ -29,9 +28,6 @@ private:
JS_DECLARE_NATIVE_FUNCTION(call); JS_DECLARE_NATIVE_FUNCTION(call);
JS_DECLARE_NATIVE_FUNCTION(to_string); JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_NATIVE_FUNCTION(symbol_has_instance); JS_DECLARE_NATIVE_FUNCTION(symbol_has_instance);
// 20.2.3: The Function prototype object has a "name" property whose value is the empty String.
FlyString m_name;
}; };
} }

View file

@ -34,7 +34,7 @@ public:
virtual ThrowCompletionOr<Value> call(); virtual ThrowCompletionOr<Value> call();
virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target); virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target);
virtual FlyString const& name() const override { return m_name; } FlyString const& name() const { return m_name; }
virtual bool is_strict_mode() const override; virtual bool is_strict_mode() const override;
virtual bool has_constructor() const override { return false; } virtual bool has_constructor() const override { return false; }
virtual Realm* realm() const override { return m_realm; } virtual Realm* realm() const override { return m_realm; }

View file

@ -897,10 +897,4 @@ void ProxyObject::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_handler); visitor.visit(m_handler);
} }
FlyString const& ProxyObject::name() const
{
VERIFY(is_function());
return static_cast<FunctionObject&>(*m_target).name();
}
} }

View file

@ -21,7 +21,6 @@ public:
virtual ~ProxyObject() override = default; virtual ~ProxyObject() override = default;
virtual FlyString const& name() const override;
virtual bool has_constructor() const override; virtual bool has_constructor() const override;
Object const& target() const { return m_target; } Object const& target() const { return m_target; }

View file

@ -22,9 +22,6 @@ public:
virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override; virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
// FIXME: Remove this (and stop inventing random internal slots that shouldn't exist, jeez)
virtual FlyString const& name() const override { return m_wrapped_target_function->name(); }
virtual Realm* realm() const override { return m_realm; } virtual Realm* realm() const override { return m_realm; }
FunctionObject const& wrapped_target_function() const { return m_wrapped_target_function; } FunctionObject const& wrapped_target_function() const { return m_wrapped_target_function; }