Selaa lähdekoodia

LibJS: Don't discard ThrowCompletionOr<void> from declaration iteration

Luke Wilde 2 vuotta sitten
vanhempi
commit
f4be95af69

+ 25 - 15
Userland/Libraries/LibJS/AST.cpp

@@ -779,14 +779,16 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, Vector<Deprec
         if (declaration) {
             loop_env = new_declarative_environment(*old_environment);
             auto is_const = declaration->is_constant_declaration();
-            declaration->for_each_bound_name([&](auto const& name) {
+            // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
+            //       an exception should not result from `for_each_bound_name`.
+            MUST(declaration->for_each_bound_name([&](auto const& name) {
                 if (is_const) {
                     MUST(loop_env->create_immutable_binding(vm, name, true));
                 } else {
                     MUST(loop_env->create_mutable_binding(vm, name, false));
                     ++per_iteration_bindings_size;
                 }
-            });
+            }));
 
             interpreter.vm().running_execution_context().lexical_environment = loop_env;
         }
@@ -979,7 +981,9 @@ struct ForInOfHeadState {
 
             // 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) {
+            // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
+            //       an exception should not result from `for_each_bound_name`.
+            MUST(for_declaration.for_each_bound_name([&](auto const& name) {
                 if (first_name.is_empty())
                     first_name = name;
 
@@ -993,7 +997,7 @@ struct ForInOfHeadState {
                     // i. Perform ! environment.CreateMutableBinding(name, false).
                     MUST(iteration_environment->create_mutable_binding(vm, name, false));
                 }
-            });
+            }));
             interpreter.vm().running_execution_context().lexical_environment = iteration_environment;
 
             if (!destructuring) {
@@ -1074,18 +1078,20 @@ static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& i
             } else {
                 state.lhs_kind = ForInOfHeadState::LexicalBinding;
                 new_environment = new_declarative_environment(*interpreter.lexical_environment());
-                variable_declaration.for_each_bound_name([&](auto const& name) {
+                // NOTE: Due to the use of MUST with `create_mutable_binding` below, an exception should not result from `for_each_bound_name`.
+                MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
                     MUST(new_environment->create_mutable_binding(vm, name, false));
-                });
+                }));
             }
         } else {
             VERIFY(is<UsingDeclaration>(ast_ptr->ptr()));
             auto& declaration = static_cast<UsingDeclaration const&>(*(*ast_ptr));
             state.lhs_kind = ForInOfHeadState::LexicalBinding;
             new_environment = new_declarative_environment(*interpreter.lexical_environment());
-            declaration.for_each_bound_name([&](auto const& name) {
+            // NOTE: Due to the use of MUST with `create_mutable_binding` below, an exception should not result from `for_each_bound_name`.
+            MUST(declaration.for_each_bound_name([&](auto const& name) {
                 MUST(new_environment->create_mutable_binding(vm, name, false));
-            });
+            }));
         }
 
         if (new_environment) {
@@ -2071,7 +2077,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::class_definition_e
         class_constructor->add_private_method(private_method);
 
     for (auto& method : static_private_methods)
-        class_constructor->private_method_or_accessor_add(move(method));
+        TRY(class_constructor->private_method_or_accessor_add(move(method)));
 
     for (auto& element : static_elements) {
         TRY(element.visit(
@@ -3983,10 +3989,11 @@ Completion TryStatement::execute(Interpreter& interpreter) const
             },
             [&](NonnullRefPtr<BindingPattern const> const& pattern) {
                 // 3. For each element argName of the BoundNames of CatchParameter, do
-                pattern->for_each_bound_name([&](auto& name) {
+                // NOTE: Due to the use of MUST with `create_mutable_binding` below, an exception should not result from `for_each_bound_name`.
+                MUST(pattern->for_each_bound_name([&](auto& name) {
                     // a. Perform ! catchEnv.CreateMutableBinding(argName, false).
                     MUST(catch_environment->create_mutable_binding(vm, name, false));
-                });
+                }));
             });
 
         // 4. Set the running execution context's LexicalEnvironment to catchEnv.
@@ -4725,16 +4732,19 @@ void ScopeNode::block_declaration_instantiation(Interpreter& interpreter, Enviro
     VERIFY(environment);
     auto* private_environment = vm.running_execution_context().private_environment;
     // Note: All the calls here are ! and thus we do not need to TRY this callback.
-    for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
+    //       We use MUST to ensure it does not throw and to avoid discarding the returned ThrowCompletionOr<void>.
+    MUST(for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
         auto is_constant_declaration = declaration.is_constant_declaration();
-        declaration.for_each_bound_name([&](auto const& name) {
+        // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
+        //       an exception should not result from `for_each_bound_name`.
+        MUST(declaration.for_each_bound_name([&](auto const& name) {
             if (is_constant_declaration) {
                 MUST(environment->create_immutable_binding(vm, name, true));
             } else {
                 if (!MUST(environment->has_binding(name)))
                     MUST(environment->create_mutable_binding(vm, name, false));
             }
-        });
+        }));
 
         if (is<FunctionDeclaration>(declaration)) {
             auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration);
@@ -4742,7 +4752,7 @@ void ScopeNode::block_declaration_instantiation(Interpreter& interpreter, Enviro
             VERIFY(is<DeclarativeEnvironment>(*environment));
             static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function_declaration.name(), function);
         }
-    });
+    }));
 }
 
 // 16.1.7 GlobalDeclarationInstantiation ( script, env ), https://tc39.es/ecma262/#sec-globaldeclarationinstantiation

+ 15 - 10
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -44,7 +44,8 @@ Bytecode::CodeGenerationErrorOr<void> ScopeNode::generate_bytecode(Bytecode::Gen
 
         (void)for_each_lexically_scoped_declaration([&](Declaration const& declaration) -> ThrowCompletionOr<void> {
             auto is_constant_declaration = declaration.is_constant_declaration();
-            declaration.for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(declaration.for_each_bound_name([&](auto const& name) {
                 auto index = generator.intern_identifier(name);
                 // NOTE: BlockDeclarationInstantiation takes as input the new lexical environment that was created and checks if there is a binding for the current name only in this new scope.
                 //       For example: `{ let a = 1; { let a = 2; } }`. The second `a` will shadow the first `a` instead of re-initializing or setting it.
@@ -52,7 +53,7 @@ Bytecode::CodeGenerationErrorOr<void> ScopeNode::generate_bytecode(Bytecode::Gen
                     generator.register_binding(index);
                     generator.emit<Bytecode::Op::CreateVariable>(index, Bytecode::Op::EnvironmentMode::Lexical, is_constant_declaration);
                 }
-            });
+            }));
 
             if (is<FunctionDeclaration>(declaration)) {
                 auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration);
@@ -257,13 +258,14 @@ Bytecode::CodeGenerationErrorOr<void> ScopeNode::generate_bytecode(Bytecode::Gen
         // FIXME: Implement this boi correctly.
         (void)for_each_lexically_scoped_declaration([&](Declaration const& declaration) -> ThrowCompletionOr<void> {
             auto is_constant_declaration = declaration.is_constant_declaration();
-            declaration.for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(declaration.for_each_bound_name([&](auto const& name) {
                 auto index = generator.intern_identifier(name);
                 if (is_constant_declaration || !generator.has_binding(index)) {
                     generator.register_binding(index);
                     generator.emit<Bytecode::Op::CreateVariable>(index, Bytecode::Op::EnvironmentMode::Lexical, is_constant_declaration);
                 }
-            });
+            }));
 
             if (is<FunctionDeclaration>(declaration)) {
                 auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration);
@@ -1001,11 +1003,12 @@ Bytecode::CodeGenerationErrorOr<void> ForStatement::generate_labelled_evaluation
                 generator.begin_variable_scope(Bytecode::Generator::BindingMode::Lexical, Bytecode::Generator::SurroundingScopeKind::Block);
 
                 bool is_const = variable_declaration.is_constant_declaration();
-                variable_declaration.for_each_bound_name([&](auto const& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
                     auto index = generator.intern_identifier(name);
                     generator.register_binding(index);
                     generator.emit<Bytecode::Op::CreateVariable>(index, Bytecode::Op::EnvironmentMode::Lexical, is_const);
-                });
+                }));
             }
         }
 
@@ -2475,12 +2478,13 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
             // b. Let newEnv be NewDeclarativeEnvironment(oldEnv).
             generator.begin_variable_scope();
             // c. For each String name of uninitializedBoundNames, do
-            variable_declaration.for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
                 // i. Perform ! newEnv.CreateMutableBinding(name, false).
                 auto identifier = generator.intern_identifier(name);
                 generator.register_binding(identifier);
                 generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
-            });
+            }));
             // d. Set the running execution context's LexicalEnvironment to newEnv.
             // NOTE: Done by CreateEnvironment.
         }
@@ -2634,7 +2638,8 @@ static Bytecode::CodeGenerationErrorOr<void> for_in_of_body_evaluation(Bytecode:
         // NOTE: We just made it.
         auto& variable_declaration = static_cast<VariableDeclaration const&>(*lhs.get<NonnullRefPtr<ASTNode const>>());
         // 2. For each element name of the BoundNames of ForBinding, do
-        variable_declaration.for_each_bound_name([&](auto const& name) {
+        // NOTE: Nothing in the callback throws an exception.
+        MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
             auto identifier = generator.intern_identifier(name);
             generator.register_binding(identifier, Bytecode::Generator::BindingMode::Lexical);
             // a. If IsConstantDeclaration of LetOrConst is true, then
@@ -2647,7 +2652,7 @@ static Bytecode::CodeGenerationErrorOr<void> for_in_of_body_evaluation(Bytecode:
                 // i. Perform ! environment.CreateMutableBinding(name, false).
                 generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
             }
-        });
+        }));
         // 3. Return unused.
         // NOTE: No need to do that as we've inlined this.
 

+ 51 - 34
Userland/Libraries/LibJS/Parser.cpp

@@ -70,9 +70,10 @@ public:
                     scope_pusher.m_forbidden_lexical_names.set(name);
                 },
                 [&](NonnullRefPtr<BindingPattern const> const& binding_pattern) {
-                    binding_pattern->for_each_bound_name([&](auto const& name) {
+                    // NOTE: Nothing in the callback throws an exception.
+                    MUST(binding_pattern->for_each_bound_name([&](auto const& name) {
                         scope_pusher.m_forbidden_lexical_names.set(name);
-                    });
+                    }));
                 });
         }
         return scope_pusher;
@@ -94,9 +95,10 @@ public:
         if (init && is<VariableDeclaration>(*init)) {
             auto& variable_declaration = static_cast<VariableDeclaration const&>(*init);
             if (variable_declaration.declaration_kind() != DeclarationKind::Var) {
-                variable_declaration.for_each_bound_name([&](auto const& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
                     scope_pusher.m_forbidden_var_names.set(name);
-                });
+                }));
             }
         }
 
@@ -107,9 +109,10 @@ public:
     {
         ScopePusher scope_pusher(parser, nullptr, ScopeLevel::NotTopLevel);
         if (pattern) {
-            pattern->for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(pattern->for_each_bound_name([&](auto const& name) {
                 scope_pusher.m_forbidden_var_names.set(name);
-            });
+            }));
         } else if (!parameter.is_empty()) {
             scope_pusher.m_var_names.set(parameter);
         }
@@ -129,17 +132,19 @@ public:
     void add_declaration(NonnullRefPtr<Declaration const> declaration)
     {
         if (declaration->is_lexical_declaration()) {
-            declaration->for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(declaration->for_each_bound_name([&](auto const& name) {
                 if (m_var_names.contains(name) || m_forbidden_lexical_names.contains(name) || m_function_names.contains(name))
                     throw_identifier_declared(name, declaration);
 
                 if (m_lexical_names.set(name) != AK::HashSetResult::InsertedNewEntry)
                     throw_identifier_declared(name, declaration);
-            });
+            }));
 
             m_node->add_lexical_declaration(move(declaration));
         } else if (!declaration->is_function_declaration()) {
-            declaration->for_each_bound_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(declaration->for_each_bound_name([&](auto const& name) {
                 ScopePusher* pusher = this;
                 while (true) {
                     if (pusher->m_lexical_names.contains(name)
@@ -156,16 +161,17 @@ public:
                 }
                 VERIFY(pusher->is_top_level() && pusher->m_node);
                 pusher->m_node->add_var_scoped_declaration(declaration);
-            });
+            }));
 
             VERIFY(m_top_level_scope);
             m_top_level_scope->m_node->add_var_scoped_declaration(move(declaration));
         } else {
             if (m_scope_level != ScopeLevel::NotTopLevel && m_scope_level != ScopeLevel::ModuleTopLevel) {
                 // Only non-top levels and Module don't var declare the top functions
-                declaration->for_each_bound_name([&](auto const& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(declaration->for_each_bound_name([&](auto const& name) {
                     m_var_names.set(name);
-                });
+                }));
                 m_node->add_var_scoped_declaration(move(declaration));
             } else {
                 VERIFY(is<FunctionDeclaration>(*declaration));
@@ -567,16 +573,18 @@ void Parser::parse_module(Program& program)
 
             auto const& exported_name = entry.local_or_import_name;
             bool found = false;
-            program.for_each_lexically_declared_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(program.for_each_lexically_declared_name([&](auto const& name) {
                 if (name == exported_name)
                     found = true;
-            });
+            }));
             if (found)
                 continue;
-            program.for_each_var_declared_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(program.for_each_var_declared_name([&](auto const& name) {
                 if (name == exported_name)
                     found = true;
-            });
+            }));
             for (auto& import : program.imports()) {
                 if (import.has_bound_name(exported_name)) {
                     found = true;
@@ -2532,7 +2540,8 @@ NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionPar
                     parameter_names.append(parameter_name);
                 },
                 [&](NonnullRefPtr<BindingPattern const> const& binding) {
-                    binding->for_each_bound_name([&](auto& bound_name) {
+                    // NOTE: Nothing in the callback throws an exception.
+                    MUST(binding->for_each_bound_name([&](auto& bound_name) {
                         if (function_kind == FunctionKind::Generator && bound_name == "yield"sv)
                             syntax_error("Parameter name 'yield' not allowed in this context");
 
@@ -2546,7 +2555,7 @@ NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionPar
                             }
                         }
                         parameter_names.append(bound_name);
-                    });
+                    }));
                 });
         }
     }
@@ -2686,10 +2695,11 @@ Vector<FunctionParameter> Parser::parse_formal_parameters(int& function_length,
                 },
                 [&](NonnullRefPtr<BindingPattern const> const& bindings) {
                     bool found_duplicate = false;
-                    bindings->for_each_bound_name([&](auto& bound_name) {
+                    // NOTE: Nothing in the callback throws an exception.
+                    MUST(bindings->for_each_bound_name([&](auto& bound_name) {
                         if (bound_name == parameter_name)
                             found_duplicate = true;
-                    });
+                    }));
                     return found_duplicate;
                 });
 
@@ -2951,14 +2961,15 @@ RefPtr<BindingPattern const> Parser::parse_binding_pattern(Parser::AllowDuplicat
     pattern->kind = kind;
 
     Vector<StringView> bound_names;
-    pattern->for_each_bound_name([&](auto& name) {
+    // NOTE: Nothing in the callback throws an exception.
+    MUST(pattern->for_each_bound_name([&](auto& name) {
         if (allow_duplicates == AllowDuplicates::No) {
             if (bound_names.contains_slow(name))
                 syntax_error("Duplicate parameter names in bindings");
             bound_names.append(name);
         }
         check_identifier_name_for_assignment_validity(name);
-    });
+    }));
 
     return pattern;
 }
@@ -3018,10 +3029,11 @@ NonnullRefPtr<VariableDeclaration const> Parser::parse_variable_declaration(IsFo
         Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>, Empty> target {};
         if (auto pattern = parse_binding_pattern(declaration_kind != DeclarationKind::Var ? AllowDuplicates::No : AllowDuplicates::Yes, AllowMemberExpressions::No)) {
             if ((declaration_kind == DeclarationKind::Let || declaration_kind == DeclarationKind::Const)) {
-                pattern->for_each_bound_name([this](auto& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(pattern->for_each_bound_name([this](auto& name) {
                     if (name == "let"sv)
                         syntax_error("Lexical binding may not be called 'let'");
-                });
+                }));
             }
 
             target = pattern.release_nonnull();
@@ -3454,11 +3466,12 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
     HashTable<DeprecatedFlyString> bound_names;
 
     if (pattern_parameter) {
-        pattern_parameter->for_each_bound_name(
+        // NOTE: Nothing in the callback throws an exception.
+        MUST(pattern_parameter->for_each_bound_name(
             [&](auto& name) {
                 check_identifier_name_for_assignment_validity(name);
                 bound_names.set(name);
-            });
+            }));
     }
 
     if (!parameter.is_empty()) {
@@ -3469,10 +3482,11 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
     ScopePusher catch_scope = ScopePusher::catch_scope(*this, pattern_parameter, parameter);
     auto body = parse_block_statement();
 
-    body->for_each_lexically_declared_name([&](auto const& name) {
+    // NOTE: Nothing in the callback throws an exception.
+    MUST(body->for_each_lexically_declared_name([&](auto const& name) {
         if (bound_names.contains(name))
             syntax_error(DeprecatedString::formatted("Identifier '{}' already declared as catch parameter", name));
-    });
+    }));
 
     if (pattern_parameter) {
         return create_ast_node<CatchClause>(
@@ -3612,10 +3626,11 @@ NonnullRefPtr<Statement const> Parser::parse_for_statement()
             } else {
                 // This does not follow the normal declaration structure so we need additional checks.
                 HashTable<DeprecatedFlyString> bound_names;
-                declaration->for_each_bound_name([&](auto const& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(declaration->for_each_bound_name([&](auto const& name) {
                     if (bound_names.set(name) != AK::HashSetResult::InsertedNewEntry)
                         syntax_error(DeprecatedString::formatted("Identifier '{}' already declared in for loop initializer", name), declaration->source_range().start);
-                });
+                }));
             }
 
             if (match_for_in_of()) {
@@ -4650,9 +4665,10 @@ NonnullRefPtr<ExportStatement const> Parser::parse_export_statement(Program& pro
                             entries_with_location.append({ ExportEntry::named_export(identifier->string(), identifier->string()), identifier->source_range().start });
                         },
                         [&](NonnullRefPtr<BindingPattern const> const& binding) {
-                            binding->for_each_bound_name([&](auto& name) {
+                            // NOTE: Nothing in the callback throws an exception.
+                            MUST(binding->for_each_bound_name([&](auto& name) {
                                 entries_with_location.append({ ExportEntry::named_export(name, name), decl_position });
-                            });
+                            }));
                         });
                 }
             }
@@ -4667,9 +4683,10 @@ NonnullRefPtr<ExportStatement const> Parser::parse_export_statement(Program& pro
                         entries_with_location.append({ ExportEntry::named_export(identifier->string(), identifier->string()), identifier->source_range().start });
                     },
                     [&](NonnullRefPtr<BindingPattern const> const& binding) {
-                        binding->for_each_bound_name([&](auto& name) {
+                        // NOTE: Nothing in the callback throws an exception.
+                        MUST(binding->for_each_bound_name([&](auto& name) {
                             entries_with_location.append({ ExportEntry::named_export(name, name), variable_position });
-                        });
+                        }));
                     });
             }
             expression = variable_declaration;

+ 28 - 16
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -355,10 +355,11 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
                 if (pattern->contains_expression())
                     has_parameter_expressions = true;
 
-                pattern->for_each_bound_name([&](auto& name) {
+                // NOTE: Nothing in the callback throws an exception.
+                MUST(pattern->for_each_bound_name([&](auto& name) {
                     if (parameter_names.set(name) != AK::HashSetResult::InsertedNewEntry)
                         has_duplicates = true;
-                });
+                }));
             });
     }
 
@@ -374,10 +375,11 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
     Vector<FunctionDeclaration const&> functions_to_initialize;
 
     if (scope_body) {
-        scope_body->for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) {
+        // NOTE: Nothing in the callback throws an exception.
+        MUST(scope_body->for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) {
             if (function_names.set(function.name()) == AK::HashSetResult::InsertedNewEntry)
                 functions_to_initialize.append(function);
-        });
+        }));
 
         auto const& arguments_name = vm.names.arguments.as_string();
 
@@ -385,10 +387,11 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
             arguments_object_needed = false;
 
         if (!has_parameter_expressions && arguments_object_needed) {
-            scope_body->for_each_lexically_declared_name([&](auto const& name) {
+            // NOTE: Nothing in the callback throws an exception.
+            MUST(scope_body->for_each_lexically_declared_name([&](auto const& name) {
                 if (name == arguments_name)
                     arguments_object_needed = false;
-            });
+            }));
         }
     } else {
         arguments_object_needed = false;
@@ -489,12 +492,14 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
 
     if (!has_parameter_expressions) {
         if (scope_body) {
-            scope_body->for_each_var_declared_name([&](auto const& name) {
+            // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below,
+            //       an exception should not result from `for_each_var_declared_name`.
+            MUST(scope_body->for_each_var_declared_name([&](auto const& name) {
                 if (!parameter_names.contains(name) && instantiated_var_names.set(name) == AK::HashSetResult::InsertedNewEntry) {
                     MUST(environment->create_mutable_binding(vm, name, false));
                     MUST(environment->initialize_binding(vm, name, js_undefined(), Environment::InitializeBindingHint::Normal));
                 }
-            });
+            }));
         }
         var_environment = environment;
     } else {
@@ -502,7 +507,9 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
         callee_context.variable_environment = var_environment;
 
         if (scope_body) {
-            scope_body->for_each_var_declared_name([&](auto const& name) {
+            // NOTE: Due to the use of MUST with `create_mutable_binding`, `get_binding_value` and `initialize_binding` below,
+            //       an exception should not result from `for_each_var_declared_name`.
+            MUST(scope_body->for_each_var_declared_name([&](auto const& name) {
                 if (instantiated_var_names.set(name) != AK::HashSetResult::InsertedNewEntry)
                     return;
                 MUST(var_environment->create_mutable_binding(vm, name, false));
@@ -514,13 +521,15 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
                     initial_value = MUST(environment->get_binding_value(vm, name, false));
 
                 MUST(var_environment->initialize_binding(vm, name, initial_value, Environment::InitializeBindingHint::Normal));
-            });
+            }));
         }
     }
 
     // B.3.2.1 Changes to FunctionDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
     if (!m_strict && scope_body) {
-        scope_body->for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) {
+        // 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();
             if (parameter_names.contains(function_name))
                 return;
@@ -532,7 +541,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
             }
 
             function_declaration.set_should_do_additional_annexB_steps();
-        });
+        }));
     }
 
     GCPtr<Environment> lex_environment;
@@ -565,14 +574,17 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
         return {};
 
     if (!Bytecode::Interpreter::current()) {
-        scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
-            declaration.for_each_bound_name([&](auto const& name) {
+        // NOTE: Due to the use of MUST in the callback, an exception should not result from `for_each_lexically_scoped_declaration`.
+        MUST(scope_body->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
+            // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
+            //       an exception should not result from `for_each_bound_name`.
+            MUST(declaration.for_each_bound_name([&](auto const& name) {
                 if (declaration.is_constant_declaration())
                     MUST(lex_environment->create_immutable_binding(vm, name, true));
                 else
                     MUST(lex_environment->create_mutable_binding(vm, name, false));
-            });
-        });
+            }));
+        }));
     }
 
     auto* private_environment = callee_context.private_environment;

+ 11 - 6
Userland/Libraries/LibJS/SourceTextModule.cpp

@@ -436,7 +436,9 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
 
     // 21. For each element d of varDeclarations, do
     // a. For each element dn of the BoundNames of d, do
-    m_ecmascript_code->for_each_var_declared_name([&](auto const& name) {
+    // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below,
+    //       an exception should not result from `for_each_var_declared_name`.
+    MUST(m_ecmascript_code->for_each_var_declared_name([&](auto const& name) {
         // i. If dn is not an element of declaredVarNames, then
         if (!declared_var_names.contains_slow(name)) {
             // 1. Perform ! env.CreateMutableBinding(dn, false).
@@ -448,7 +450,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
             // 3. Append dn to declaredVarNames.
             declared_var_names.empend(name);
         }
-    });
+    }));
 
     // 22. Let lexDeclarations be the LexicallyScopedDeclarations of code.
     // Note: We only loop through them in step 24.
@@ -457,9 +459,12 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
     PrivateEnvironment* private_environment = nullptr;
 
     // 24. For each element d of lexDeclarations, do
-    m_ecmascript_code->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
+    // NOTE: Due to the use of MUST in the callback, an exception should not result from `for_each_lexically_scoped_declaration`.
+    MUST(m_ecmascript_code->for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
         // a. For each element dn of the BoundNames of d, do
-        declaration.for_each_bound_name([&](DeprecatedFlyString const& name) {
+        // NOTE: Due to the use of MUST with `create_immutable_binding`, `create_mutable_binding` and `initialize_binding` below,
+        //       an exception should not result from `for_each_bound_name`.
+        MUST(declaration.for_each_bound_name([&](DeprecatedFlyString const& name) {
             // i. If IsConstantDeclaration of d is true, then
             if (declaration.is_constant_declaration()) {
                 // 1. Perform ! env.CreateImmutableBinding(dn, true).
@@ -487,8 +492,8 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
                 // 2. Perform ! env.InitializeBinding(dn, fo, normal).
                 MUST(environment->initialize_binding(vm, name, function, Environment::InitializeBindingHint::Normal));
             }
-        });
-    });
+        }));
+    }));
 
     // Note: The default export name is also part of the local lexical declarations but
     //       instead of making that a special case in the parser we just check it here.