1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:17:45 +00:00

LibJS/Bytecode: Reorder function compilation to ensure correct hoisting

Fixes 37 test262 tests. :^)

Co-authored-by: Luke Wilde <lukew@serenityos.org>
This commit is contained in:
Andreas Kling 2023-06-17 14:20:48 +02:00
parent 9c568282dc
commit 743943a042

View file

@ -833,7 +833,6 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
}
if (bytecode_interpreter) {
if (!m_bytecode_executable) {
auto compile = [&](auto& node, auto kind, auto name) -> ThrowCompletionOr<NonnullOwnPtr<Bytecode::Executable>> {
auto executable_result = Bytecode::Generator::generate(node, kind);
if (executable_result.is_error())
@ -853,8 +852,14 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
return bytecode_executable;
};
m_bytecode_executable = TRY(compile(*m_ecmascript_code, m_kind, m_name));
// NOTE: There's a subtle ordering issue here:
// - We have to compile the default parameter values before instantiating the function.
// - We have to instantiate the function before compiling the function body.
// This is why FunctionDeclarationInstantiation is invoked in the middle.
// The issue is that FunctionDeclarationInstantiation may mark certain functions as hoisted
// per Annex B. This affects code generation for FunctionDeclaration nodes.
if (!m_bytecode_executable) {
size_t default_parameter_index = 0;
for (auto& parameter : m_formal_parameters) {
if (!parameter.default_value)
@ -863,7 +868,13 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
m_default_parameter_bytecode_executables.append(move(executable));
}
}
TRY(function_declaration_instantiation(nullptr));
if (!m_bytecode_executable) {
m_bytecode_executable = TRY(compile(*m_ecmascript_code, m_kind, m_name));
}
auto result_and_frame = bytecode_interpreter->run_and_return_frame(*m_bytecode_executable, nullptr);
VERIFY(result_and_frame.frame != nullptr);