diff options
author | Luke Wilde <lukew@serenityos.org> | 2022-06-11 23:24:55 +0100 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-06-13 07:13:03 +0430 |
commit | 125a71d36dcaf2c5e5263cc8b3368609ccbe17e3 (patch) | |
tree | 0ebb3a20c06107cd3ff7ea9df29374aa917e6e05 | |
parent | 9ad807d08bd373aaf8172f02c07aeb198f25b8ce (diff) | |
download | serenity-125a71d36dcaf2c5e5263cc8b3368609ccbe17e3.zip |
LibJS/Bytecode: Define named functions as a variable inside their scope
This allows you to recurse into a named function that is stored in a
variable. For example, this would previously print "wrong" instead of
"right":
```js
function g() { console.log("wrong") }
f = function g(i) { if (i !== 1) g(1); else console.log("right"); }
f()
```
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index d0f9ce0329..27184a4106 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1010,7 +1010,23 @@ Bytecode::CodeGenerationErrorOr<void> FunctionDeclaration::generate_bytecode(Byt Bytecode::CodeGenerationErrorOr<void> FunctionExpression::generate_bytecode(Bytecode::Generator& generator) const { + bool has_name = !name().is_empty(); + Optional<Bytecode::IdentifierTableIndex> name_identifier; + + if (has_name) { + generator.begin_variable_scope(Bytecode::Generator::BindingMode::Lexical); + + name_identifier = generator.intern_identifier(name()); + generator.emit<Bytecode::Op::CreateVariable>(*name_identifier, Bytecode::Op::EnvironmentMode::Lexical, true); + } + generator.emit<Bytecode::Op::NewFunction>(*this); + + if (has_name) { + generator.emit<Bytecode::Op::SetVariable>(*name_identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical); + generator.end_variable_scope(); + } + return {}; } |