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
parent 6bd2cf3195
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())
return;
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);
}

View file

@ -1212,14 +1212,14 @@ inline ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value thi
switch (kind) {
case Op::PropertyKind::Getter: {
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)));
object->define_direct_accessor(name, &function, nullptr, Attribute::Configurable | Attribute::Enumerable);
break;
}
case Op::PropertyKind::Setter: {
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)));
object->define_direct_accessor(name, nullptr, &function, Attribute::Configurable | Attribute::Enumerable);
break;

View file

@ -39,8 +39,6 @@ BoundFunction::BoundFunction(Realm& realm, FunctionObject& bound_target_function
, m_bound_target_function(&bound_target_function)
, m_bound_this(bound_this)
, 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<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 has_constructor() const override { return m_bound_target_function->has_constructor(); }
@ -39,8 +38,6 @@ private:
GC::Ptr<FunctionObject> m_bound_target_function; // [[BoundTargetFunction]]
Value m_bound_this; // [[BoundThis]]
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; }
[[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_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<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_length(double length);

View file

@ -19,7 +19,6 @@ public:
virtual ~FunctionPrototype() override = default;
virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
virtual FlyString const& name() const override { return m_name; }
private:
explicit FunctionPrototype(Realm&);
@ -29,9 +28,6 @@ private:
JS_DECLARE_NATIVE_FUNCTION(call);
JS_DECLARE_NATIVE_FUNCTION(to_string);
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<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 has_constructor() const override { return false; }
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);
}
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 FlyString const& name() const override;
virtual bool has_constructor() const override;
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;
// 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; }
FunctionObject const& wrapped_target_function() const { return m_wrapped_target_function; }