diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 7bf76f91da..866721b093 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -314,7 +314,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Depre given_name = ""; auto has_own_name = !name().is_empty(); - auto const& used_name = has_own_name ? name() : given_name; + auto const used_name = has_own_name ? name() : given_name.view(); auto environment = NonnullGCPtr { *vm.running_execution_context().lexical_environment }; if (has_own_name) { VERIFY(environment); @@ -4805,7 +4805,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within script, do TRY(for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr { // i. Let F be StringValue of the BindingIdentifier of f. - auto& function_name = function_declaration.name(); + auto function_name = function_declaration.name(); // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for script, then // Note: This step is already performed during parsing and for_each_function_hoistable_with_annexB_extension so this always passes here. diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 127cb7ce9b..ae8fcebc9e 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -663,9 +663,41 @@ struct FunctionParameter { bool is_rest { false }; }; +class Identifier final : public Expression { +public: + explicit Identifier(SourceRange source_range, DeprecatedFlyString string) + : Expression(source_range) + , m_string(move(string)) + { + } + + DeprecatedFlyString const& string() const { return m_string; } + + bool is_local() const { return m_local_variable_index.has_value(); } + size_t local_variable_index() const + { + VERIFY(m_local_variable_index.has_value()); + return m_local_variable_index.value(); + } + void set_local_variable_index(size_t index) { m_local_variable_index = index; } + + virtual Completion execute(Interpreter&) const override; + virtual void dump(int indent) const override; + virtual ThrowCompletionOr to_reference(Interpreter&) const override; + virtual Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&) const override; + +private: + virtual bool is_identifier() const override { return true; } + + DeprecatedFlyString m_string; + mutable EnvironmentCoordinate m_cached_environment_coordinate; + + Optional m_local_variable_index; +}; + class FunctionNode { public: - DeprecatedFlyString const& name() const { return m_name; } + StringView name() const { return m_name ? m_name->string().view() : ""sv; } DeprecatedString const& source_text() const { return m_source_text; } Statement const& body() const { return *m_body; } Vector const& parameters() const { return m_parameters; }; @@ -698,7 +730,7 @@ protected: void dump(int indent, DeprecatedString const& class_name) const; private: - DeprecatedFlyString m_name; + RefPtr m_name { nullptr }; DeprecatedString m_source_text; NonnullRefPtr m_body; Vector const m_parameters; @@ -1259,38 +1291,6 @@ private: DeprecatedString m_flags; }; -class Identifier final : public Expression { -public: - explicit Identifier(SourceRange source_range, DeprecatedFlyString string) - : Expression(source_range) - , m_string(move(string)) - { - } - - DeprecatedFlyString const& string() const { return m_string; } - - bool is_local() const { return m_local_variable_index.has_value(); } - size_t local_variable_index() const - { - VERIFY(m_local_variable_index.has_value()); - return m_local_variable_index.value(); - } - void set_local_variable_index(size_t index) { m_local_variable_index = index; } - - virtual Completion execute(Interpreter&) const override; - virtual void dump(int indent) const override; - virtual ThrowCompletionOr to_reference(Interpreter&) const override; - virtual Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&) const override; - -private: - virtual bool is_identifier() const override { return true; } - - DeprecatedFlyString m_string; - mutable EnvironmentCoordinate m_cached_environment_coordinate; - - Optional m_local_variable_index; -}; - class PrivateIdentifier final : public Expression { public: explicit PrivateIdentifier(SourceRange source_range, DeprecatedFlyString string) diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 123405fa33..2592b82395 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -845,7 +845,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within body, do TRY(program.for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr { // i. Let F be StringValue of the BindingIdentifier of f. - auto& function_name = function_declaration.name(); + auto function_name = function_declaration.name(); // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for body, then // Note: This is checked during parsing and for_each_function_hoistable_with_annexB_extension so it always passes here. diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index b5a08d9bd0..6a06e05598 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -534,7 +534,7 @@ ThrowCompletionOr ECMAScriptFunctionObject::function_declaration_instantia // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below, // an exception should not result from `for_each_function_hoistable_with_annexB_extension`. MUST(scope_body->for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) { - auto& function_name = function_declaration.name(); + auto function_name = function_declaration.name(); if (parameter_names.contains(function_name)) return; // The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'.