mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:17:44 +00:00
LibJS/Bytecode: Handle awkward initialization case for duplicate var
`var` declarations can have duplicates, but duplicate `let` or `const` bindings are a syntax error. Because of this, we can sink `let` and `const` directly into the preferred_dst if available. This is not safe for `var` since the preferred_dst may be used in the initializer. This patch fixes the issue by simply skipping the preferred_dst optimization for `var` declarations.
This commit is contained in:
parent
2bbdfe0fba
commit
bc21ed151e
2 changed files with 23 additions and 3 deletions
|
@ -1452,10 +1452,15 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> VariableDeclaration
|
||||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||||
|
|
||||||
for (auto& declarator : m_declarations) {
|
for (auto& declarator : m_declarations) {
|
||||||
|
// NOTE: `var` declarations can have duplicates, but duplicate `let` or `const` bindings are a syntax error.
|
||||||
|
// Because of this, we can sink `let` and `const` directly into the preferred_dst if available.
|
||||||
|
// This is not safe for `var` since the preferred_dst may be used in the initializer.
|
||||||
Optional<Bytecode::Operand> init_dst;
|
Optional<Bytecode::Operand> init_dst;
|
||||||
if (auto const* identifier = declarator->target().get_pointer<NonnullRefPtr<Identifier const>>()) {
|
if (declaration_kind() != DeclarationKind::Var) {
|
||||||
if ((*identifier)->is_local()) {
|
if (auto const* identifier = declarator->target().get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||||
init_dst = Bytecode::Operand(Bytecode::Operand::Type::Local, (*identifier)->local_variable_index());
|
if ((*identifier)->is_local()) {
|
||||||
|
init_dst = Bytecode::Operand(Bytecode::Operand::Type::Local, (*identifier)->local_variable_index());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,3 +33,18 @@ test("Issue #8198 arrow function escapes function scope", () => {
|
||||||
f();
|
f();
|
||||||
expect(b).toBe(3);
|
expect(b).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Referencing the declared var in the initializer of a duplicate var declaration", () => {
|
||||||
|
function c(e) {
|
||||||
|
e.foo;
|
||||||
|
}
|
||||||
|
function h() {}
|
||||||
|
function go() {
|
||||||
|
var p = true;
|
||||||
|
var p = h() || c(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's all good as long as go() doesn't throw.
|
||||||
|
expect(go()).toBe(0);
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue