mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:34:59 +00:00
LibJS: Fix that constant declaration in for loop was mutable in body
This commit is contained in:
parent
714f0c3dce
commit
8319d7ac06
3 changed files with 34 additions and 4 deletions
|
@ -921,12 +921,22 @@ struct ForInOfHeadState {
|
|||
else {
|
||||
VERIFY(expression_lhs && is<VariableDeclaration>(*expression_lhs));
|
||||
iteration_environment = new_declarative_environment(*interpreter.lexical_environment());
|
||||
|
||||
auto& for_declaration = static_cast<VariableDeclaration const&>(*expression_lhs);
|
||||
|
||||
// 14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation, https://tc39.es/ecma262/#sec-runtime-semantics-fordeclarationbindinginstantiation
|
||||
// 1. For each element name of the BoundNames of ForBinding, do
|
||||
for_declaration.for_each_bound_name([&](auto const& name) {
|
||||
if (for_declaration.declaration_kind() == DeclarationKind::Const)
|
||||
MUST(iteration_environment->create_immutable_binding(vm, name, false));
|
||||
else
|
||||
MUST(iteration_environment->create_mutable_binding(vm, name, true));
|
||||
// a. If IsConstantDeclaration of LetOrConst is true, then
|
||||
if (for_declaration.is_constant_declaration()) {
|
||||
// i. Perform ! environment.CreateImmutableBinding(name, true).
|
||||
MUST(iteration_environment->create_immutable_binding(vm, name, true));
|
||||
}
|
||||
// b. Else,
|
||||
else {
|
||||
// i. Perform ! environment.CreateMutableBinding(name, false).
|
||||
MUST(iteration_environment->create_mutable_binding(vm, name, false));
|
||||
}
|
||||
});
|
||||
interpreter.vm().running_execution_context().lexical_environment = iteration_environment;
|
||||
|
||||
|
|
|
@ -98,6 +98,16 @@ describe("special left hand sides", () => {
|
|||
eval("for (f() in [0]) { expect().fail() }");
|
||||
}).toThrowWithMessage(ReferenceError, "Invalid left-hand side in assignment");
|
||||
});
|
||||
|
||||
test("Cannot change constant declaration in body", () => {
|
||||
const vals = [];
|
||||
for (const v in [1, 2]) {
|
||||
expect(() => v++).toThrowWithMessage(TypeError, "Invalid assignment to const variable");
|
||||
vals.push(v);
|
||||
}
|
||||
|
||||
expect(vals).toEqual(["0", "1"]);
|
||||
});
|
||||
});
|
||||
|
||||
test("remove properties while iterating", () => {
|
||||
|
|
|
@ -142,4 +142,14 @@ describe("special left hand sides", () => {
|
|||
eval("for (f() of [0]) { expect().fail() }");
|
||||
}).toThrowWithMessage(ReferenceError, "Invalid left-hand side in assignment");
|
||||
});
|
||||
|
||||
test("Cannot change constant declaration in body", () => {
|
||||
const vals = [];
|
||||
for (const v of [1, 2]) {
|
||||
expect(() => v++).toThrowWithMessage(TypeError, "Invalid assignment to const variable");
|
||||
vals.push(v);
|
||||
}
|
||||
|
||||
expect(vals).toEqual([1, 2]);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue