diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index 9de4b5050e..bf00c10586 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -23,7 +23,7 @@ namespace JS { -ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector parameters, i32 m_function_length, Environment* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function) +ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, FlyString name, Statement const& ecmascript_code, Vector parameters, i32 m_function_length, Environment* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function) { Object* prototype = nullptr; switch (kind) { @@ -34,31 +34,31 @@ ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_ prototype = global_object.generator_function_prototype(); break; } - return global_object.heap().allocate(global_object, global_object, name, body, move(parameters), m_function_length, parent_scope, *prototype, kind, is_strict, is_arrow_function); + return global_object.heap().allocate(global_object, global_object, move(name), ecmascript_code, move(parameters), m_function_length, parent_scope, *prototype, kind, is_strict, is_arrow_function); } -ECMAScriptFunctionObject::ECMAScriptFunctionObject(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector parameters, i32 function_length, Environment* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function) +ECMAScriptFunctionObject::ECMAScriptFunctionObject(GlobalObject& global_object, FlyString name, Statement const& ecmascript_code, Vector formal_parameters, i32 function_length, Environment* parent_scope, Object& prototype, FunctionKind kind, bool strict, bool is_arrow_function) : FunctionObject(is_arrow_function ? vm().this_value(global_object) : Value(), {}, prototype) - , m_name(name) - , m_body(body) - , m_parameters(move(parameters)) , m_environment(parent_scope) + , m_formal_parameters(move(formal_parameters)) + , m_ecmascript_code(ecmascript_code) , m_realm(vm().interpreter_if_exists() ? &vm().interpreter().realm() : nullptr) + , m_strict(strict) + , m_name(move(name)) , m_function_length(function_length) , m_kind(kind) - , m_is_strict(is_strict) , m_is_arrow_function(is_arrow_function) { // NOTE: This logic is from OrdinaryFunctionCreate, https://tc39.es/ecma262/#sec-ordinaryfunctioncreate if (m_is_arrow_function) set_this_mode(ThisMode::Lexical); - else if (m_is_strict) + else if (m_strict) set_this_mode(ThisMode::Strict); else set_this_mode(ThisMode::Global); // 15.1.3 Static Semantics: IsSimpleParameterList, https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist - set_has_simple_parameter_list(all_of(m_parameters, [&](auto& parameter) { + set_has_simple_parameter_list(all_of(m_formal_parameters, [&](auto& parameter) { if (parameter.is_rest) return false; if (parameter.default_value) @@ -104,7 +104,7 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor) FunctionEnvironment* ECMAScriptFunctionObject::create_environment(FunctionObject& function_being_invoked) { HashMap variables; - for (auto& parameter : m_parameters) { + for (auto& parameter : m_formal_parameters) { parameter.binding.visit( [&](const FlyString& name) { variables.set(name, { js_undefined(), DeclarationKind::Var }); }, [&](const NonnullRefPtr& binding) { @@ -114,8 +114,8 @@ FunctionEnvironment* ECMAScriptFunctionObject::create_environment(FunctionObject }); } - if (is(body())) { - for (auto& declaration : static_cast(body()).variables()) { + if (is(ecmascript_code())) { + for (auto& declaration : static_cast(ecmascript_code()).variables()) { for (auto& declarator : declaration.declarations()) { declarator.target().visit( [&](const NonnullRefPtr& id) { @@ -149,8 +149,8 @@ Value ECMAScriptFunctionObject::execute_function_body() auto prepare_arguments = [&] { auto& execution_context_arguments = vm.running_execution_context().arguments; - for (size_t i = 0; i < m_parameters.size(); ++i) { - auto& parameter = m_parameters[i]; + for (size_t i = 0; i < m_formal_parameters.size(); ++i) { + auto& parameter = m_formal_parameters[i]; parameter.binding.visit( [&](const auto& param) { Value argument_value; @@ -182,7 +182,7 @@ Value ECMAScriptFunctionObject::execute_function_body() if (bytecode_interpreter) { prepare_arguments(); if (!m_bytecode_executable.has_value()) { - m_bytecode_executable = Bytecode::Generator::generate(m_body, m_kind == FunctionKind::Generator); + m_bytecode_executable = Bytecode::Generator::generate(m_ecmascript_code, m_kind == FunctionKind::Generator); auto& passes = JS::Bytecode::Interpreter::optimization_pipeline(); passes.perform(*m_bytecode_executable); if constexpr (JS_BYTECODE_DEBUG) { @@ -213,7 +213,7 @@ Value ECMAScriptFunctionObject::execute_function_body() if (vm.exception()) return {}; - return ast_interpreter->execute_statement(global_object(), m_body, ScopeType::Function); + return ast_interpreter->execute_statement(global_object(), m_ecmascript_code, ScopeType::Function); } } diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h index 9c3d73781c..b609bf6ba2 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h @@ -17,14 +17,14 @@ class ECMAScriptFunctionObject final : public FunctionObject { JS_OBJECT(ECMAScriptFunctionObject, FunctionObject); public: - static ECMAScriptFunctionObject* create(GlobalObject&, const FlyString& name, const Statement& body, Vector parameters, i32 m_function_length, Environment* parent_scope, FunctionKind, bool is_strict, bool is_arrow_function = false); + static ECMAScriptFunctionObject* create(GlobalObject&, FlyString name, Statement const& ecmascript_code, Vector parameters, i32 m_function_length, Environment* parent_scope, FunctionKind, bool is_strict, bool is_arrow_function = false); - ECMAScriptFunctionObject(GlobalObject&, const FlyString& name, const Statement& body, Vector parameters, i32 m_function_length, Environment* parent_scope, Object& prototype, FunctionKind, bool is_strict, bool is_arrow_function = false); + ECMAScriptFunctionObject(GlobalObject&, FlyString name, Statement const& ecmascript_code, Vector parameters, i32 m_function_length, Environment* parent_scope, Object& prototype, FunctionKind, bool is_strict, bool is_arrow_function = false); virtual void initialize(GlobalObject&) override; virtual ~ECMAScriptFunctionObject(); - const Statement& body() const { return m_body; } - const Vector& parameters() const { return m_parameters; }; + Statement const& ecmascript_code() const { return m_ecmascript_code; } + Vector const& formal_parameters() const { return m_formal_parameters; }; virtual Value call() override; virtual Value construct(FunctionObject& new_target) override; @@ -40,7 +40,7 @@ public: virtual Realm* realm() const override { return m_realm; } protected: - virtual bool is_strict_mode() const final { return m_is_strict; } + virtual bool is_strict_mode() const final { return m_strict; } private: virtual bool is_ecmascript_function_object() const override { return true; } @@ -49,17 +49,19 @@ private: Value execute_function_body(); + // Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects + Environment* m_environment { nullptr }; // [[Environment]] + Vector const m_formal_parameters; // [[FormalParameters]] + NonnullRefPtr m_ecmascript_code; // [[ECMAScriptCode]] + Realm* m_realm { nullptr }; // [[Realm]] + bool m_strict { false }; // [[Strict]] + bool m_is_class_constructor { false }; // [[IsClassConstructor]] + FlyString m_name; - NonnullRefPtr m_body; - const Vector m_parameters; Optional m_bytecode_executable; - Environment* m_environment { nullptr }; - Realm* m_realm { nullptr }; i32 m_function_length { 0 }; FunctionKind m_kind { FunctionKind::Regular }; - bool m_is_strict { false }; bool m_is_arrow_function { false }; - bool m_is_class_constructor { false }; }; } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp index 72f0f06422..b0eff67fc3 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp @@ -121,7 +121,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string) auto& function = static_cast(*this_object); StringBuilder parameters_builder; auto first = true; - for (auto& parameter : function.parameters()) { + for (auto& parameter : function.formal_parameters()) { // FIXME: Also stringify binding patterns. if (auto* name_ptr = parameter.binding.get_pointer()) { if (!first) diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 5b33725171..1490525d8a 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -377,7 +377,7 @@ Value VM::get_variable(const FlyString& name, GlobalObject& global_object) if (context.function->is_strict_mode() || !context.function->has_simple_parameter_list()) { context.arguments_object = create_unmapped_arguments_object(global_object, context.arguments.span()); } else { - context.arguments_object = create_mapped_arguments_object(global_object, *context.function, verify_cast(context.function)->parameters(), context.arguments.span(), *lexical_environment()); + context.arguments_object = create_mapped_arguments_object(global_object, *context.function, verify_cast(context.function)->formal_parameters(), context.arguments.span(), *lexical_environment()); } } return context.arguments_object;