diff --git a/Applications/Browser/BrowserConsoleClient.cpp b/Applications/Browser/BrowserConsoleClient.cpp index d7b54c06ce0..83802161223 100644 --- a/Applications/Browser/BrowserConsoleClient.cpp +++ b/Applications/Browser/BrowserConsoleClient.cpp @@ -41,7 +41,7 @@ namespace Browser { JS::Value BrowserConsoleClient::log() { - m_console_widget.print_html(interpreter().join_arguments()); + m_console_widget.print_html(interpreter().vm().join_arguments()); return JS::js_undefined(); } @@ -50,7 +50,7 @@ JS::Value BrowserConsoleClient::info() StringBuilder html; html.append(""); html.append("(i) "); - html.append(interpreter().join_arguments()); + html.append(interpreter().vm().join_arguments()); html.append(""); m_console_widget.print_html(html.string_view()); return JS::js_undefined(); @@ -61,7 +61,7 @@ JS::Value BrowserConsoleClient::debug() StringBuilder html; html.append(""); html.append("(d) "); - html.append(interpreter().join_arguments()); + html.append(interpreter().vm().join_arguments()); html.append(""); m_console_widget.print_html(html.string_view()); return JS::js_undefined(); @@ -72,7 +72,7 @@ JS::Value BrowserConsoleClient::warn() StringBuilder html; html.append(""); html.append("(w) "); - html.append(interpreter().join_arguments()); + html.append(interpreter().vm().join_arguments()); html.append(""); m_console_widget.print_html(html.string_view()); return JS::js_undefined(); @@ -83,7 +83,7 @@ JS::Value BrowserConsoleClient::error() StringBuilder html; html.append(""); html.append("(e) "); - html.append(interpreter().join_arguments()); + html.append(interpreter().vm().join_arguments()); html.append(""); m_console_widget.print_html(html.string_view()); return JS::js_undefined(); @@ -98,7 +98,7 @@ JS::Value BrowserConsoleClient::clear() JS::Value BrowserConsoleClient::trace() { StringBuilder html; - html.append(interpreter().join_arguments()); + html.append(interpreter().vm().join_arguments()); auto trace = get_trace(); for (auto& function_name : trace) { if (function_name.is_empty()) diff --git a/Applications/Browser/ConsoleWidget.cpp b/Applications/Browser/ConsoleWidget.cpp index e19a68ea385..5ef3e545a70 100644 --- a/Applications/Browser/ConsoleWidget.cpp +++ b/Applications/Browser/ConsoleWidget.cpp @@ -92,7 +92,7 @@ ConsoleWidget::ConsoleWidget() auto hint = error.source_location_hint(js_source); if (!hint.is_empty()) output_html.append(String::format("
%s
", escape_html_entities(hint).characters())); - m_interpreter->throw_exception(error.to_string()); + m_interpreter->vm().throw_exception(m_interpreter->global_object(), error.to_string()); } else { m_interpreter->run(m_interpreter->global_object(), *program); } @@ -106,7 +106,7 @@ ConsoleWidget::ConsoleWidget() return; } - print_html(JS::MarkupGenerator::html_from_value(m_interpreter->last_value())); + print_html(JS::MarkupGenerator::html_from_value(m_interpreter->vm().last_value())); }; auto& clear_button = bottom_container.add(); diff --git a/Applications/Spreadsheet/JSIntegration.cpp b/Applications/Spreadsheet/JSIntegration.cpp index 54f48a5ab54..4ffa06308d9 100644 --- a/Applications/Spreadsheet/JSIntegration.cpp +++ b/Applications/Spreadsheet/JSIntegration.cpp @@ -87,12 +87,12 @@ void SheetGlobalObject::initialize() JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name) { if (interpreter.argument_count() != 1) { - interpreter.throw_exception("Expected exactly one argument to parse_cell_name()"); + interpreter.vm().throw_exception(global_object, "Expected exactly one argument to parse_cell_name()"); return {}; } auto name_value = interpreter.argument(0); if (!name_value.is_string()) { - interpreter.throw_exception("Expected a String argument to parse_cell_name()"); + interpreter.vm().throw_exception(global_object, "Expected a String argument to parse_cell_name()"); return {}; } auto position = Sheet::parse_cell_name(name_value.as_string().string()); @@ -125,12 +125,12 @@ void WorkbookObject::initialize(JS::GlobalObject& global_object) JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet) { if (interpreter.argument_count() != 1) { - interpreter.throw_exception("Expected exactly one argument to sheet()"); + interpreter.vm().throw_exception(global_object, "Expected exactly one argument to sheet()"); return {}; } auto name_value = interpreter.argument(0); if (!name_value.is_string() && !name_value.is_number()) { - interpreter.throw_exception("Expected a String or Number argument to sheet()"); + interpreter.vm().throw_exception(global_object, "Expected a String or Number argument to sheet()"); return {}; } @@ -139,7 +139,7 @@ JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet) return {}; if (!this_object->inherits("WorkbookObject")) { - interpreter.throw_exception(JS::ErrorType::NotA, "WorkbookObject"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, "WorkbookObject"); return {}; } diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index 07a0164ccfa..bc97b603305 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -164,7 +164,7 @@ JS::Value Sheet::evaluate(const StringView& source, Cell* on_behalf_of) return exc; } - auto value = interpreter().last_value(); + auto value = interpreter().vm().last_value(); if (value.is_empty()) return JS::js_undefined(); return value; diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index d2a8a85cacb..3ec1aa3efc5 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -86,7 +86,7 @@ static String get_function_name(Interpreter& interpreter, Value value) Value ScopeNode::execute(Interpreter& interpreter, GlobalObject& global_object) const { - return interpreter.execute_statement(global_object, *this); + return interpreter.vm().execute_statement(global_object, *this); } Value FunctionDeclaration::execute(Interpreter&, GlobalObject&) const @@ -113,7 +113,7 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete if (m_callee->is_super_expression()) { // If we are calling super, |this| has not been initalized yet, and would not be meaningful to provide. - auto new_target = interpreter.get_new_target(); + auto new_target = interpreter.vm().get_new_target(); ASSERT(new_target.is_function()); return { js_undefined(), new_target }; } @@ -125,7 +125,7 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete if (interpreter.exception()) return {}; if (is_super_property_lookup && (lookup_target.is_null() || lookup_target.is_undefined())) { - interpreter.throw_exception(ErrorType::ObjectPrototypeNullOrUndefinedOnSuperPropertyAccess, lookup_target.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectPrototypeNullOrUndefinedOnSuperPropertyAccess, lookup_target.to_string_without_side_effects().characters()); return {}; } @@ -160,9 +160,9 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj } else { expression_string = static_cast(*m_callee).to_string_approximation(); } - interpreter.throw_exception(ErrorType::IsNotAEvaluatedFrom, callee.to_string_without_side_effects().characters(), call_type, expression_string.characters()); + interpreter.vm().throw_exception(global_object, ErrorType::IsNotAEvaluatedFrom, callee.to_string_without_side_effects().characters(), call_type, expression_string.characters()); } else { - interpreter.throw_exception(ErrorType::IsNotA, callee.to_string_without_side_effects().characters(), call_type); + interpreter.vm().throw_exception(global_object, ErrorType::IsNotA, callee.to_string_without_side_effects().characters(), call_type); } return {}; } @@ -192,17 +192,17 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj Object* new_object = nullptr; Value result; if (is_new_expression()) { - result = interpreter.construct(function, function, move(arguments), global_object); + result = interpreter.vm().construct(function, function, move(arguments), global_object); if (result.is_object()) new_object = &result.as_object(); } else if (m_callee->is_super_expression()) { auto* super_constructor = interpreter.current_environment()->current_function()->prototype(); // FIXME: Functions should track their constructor kind. if (!super_constructor || !super_constructor->is_function()) { - interpreter.throw_exception(ErrorType::NotAConstructor, "Super constructor"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAConstructor, "Super constructor"); return {}; } - result = interpreter.construct(static_cast(*super_constructor), function, move(arguments), global_object); + result = interpreter.vm().construct(static_cast(*super_constructor), function, move(arguments), global_object); if (interpreter.exception()) return {}; @@ -227,7 +227,7 @@ Value ReturnStatement::execute(Interpreter& interpreter, GlobalObject& global_ob auto value = argument() ? argument()->execute(interpreter, global_object) : js_undefined(); if (interpreter.exception()) return {}; - interpreter.unwind(ScopeType::Function); + interpreter.vm().unwind(ScopeType::Function); return value; } @@ -238,10 +238,10 @@ Value IfStatement::execute(Interpreter& interpreter, GlobalObject& global_object return {}; if (predicate_result.to_boolean()) - return interpreter.execute_statement(global_object, *m_consequent); + return interpreter.vm().execute_statement(global_object, *m_consequent); if (m_alternate) - return interpreter.execute_statement(global_object, *m_alternate); + return interpreter.vm().execute_statement(global_object, *m_alternate); return js_undefined(); } @@ -252,7 +252,7 @@ Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_obj while (m_test->execute(interpreter, global_object).to_boolean()) { if (interpreter.exception()) return {}; - last_value = interpreter.execute_statement(global_object, *m_body); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return {}; } @@ -266,7 +266,7 @@ Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_o do { if (interpreter.exception()) return {}; - last_value = interpreter.execute_statement(global_object, *m_body); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return {}; } while (m_test->execute(interpreter, global_object).to_boolean()); @@ -283,12 +283,12 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec NonnullRefPtrVector decls; decls.append(*static_cast(m_init.ptr())); wrapper->add_variables(decls); - interpreter.enter_scope(*wrapper, {}, ScopeType::Block, global_object); + interpreter.vm().enter_scope(*wrapper, {}, ScopeType::Block, global_object); } auto wrapper_cleanup = ScopeGuard([&] { if (wrapper) - interpreter.exit_scope(*wrapper); + interpreter.vm().exit_scope(*wrapper); }); Value last_value = js_undefined(); @@ -306,14 +306,14 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec return {}; if (!test_result.to_boolean()) break; - last_value = interpreter.execute_statement(global_object, *m_body); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) { - if (interpreter.should_unwind_until(ScopeType::Continuable, m_label)) { - interpreter.stop_unwind(); - } else if (interpreter.should_unwind_until(ScopeType::Breakable, m_label)) { - interpreter.stop_unwind(); + if (interpreter.vm().should_unwind()) { + if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) { + interpreter.vm().stop_unwind(); + } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) { + interpreter.vm().stop_unwind(); break; } else { return js_undefined(); @@ -327,14 +327,14 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec } } else { while (true) { - last_value = interpreter.execute_statement(global_object, *m_body); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) { - if (interpreter.should_unwind_until(ScopeType::Continuable, m_label)) { - interpreter.stop_unwind(); - } else if (interpreter.should_unwind_until(ScopeType::Breakable, m_label)) { - interpreter.stop_unwind(); + if (interpreter.vm().should_unwind()) { + if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) { + interpreter.vm().stop_unwind(); + } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) { + interpreter.vm().stop_unwind(); break; } else { return js_undefined(); @@ -359,7 +359,7 @@ static FlyString variable_from_for_declaration(Interpreter& interpreter, GlobalO ASSERT(!variable_declaration->declarations().is_empty()); if (variable_declaration->declaration_kind() != DeclarationKind::Var) { wrapper = create_ast_node(); - interpreter.enter_scope(*wrapper, {}, ScopeType::Block, global_object); + interpreter.vm().enter_scope(*wrapper, {}, ScopeType::Block, global_object); } variable_declaration->execute(interpreter, global_object); variable_name = variable_declaration->declarations().first().id().string(); @@ -381,7 +381,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj auto variable_name = variable_from_for_declaration(interpreter, global_object, m_lhs, wrapper); auto wrapper_cleanup = ScopeGuard([&] { if (wrapper) - interpreter.exit_scope(*wrapper); + interpreter.vm().exit_scope(*wrapper); }); auto last_value = js_undefined(); auto rhs_result = m_rhs->execute(interpreter, global_object); @@ -391,17 +391,17 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj while (object) { auto property_names = object->get_own_properties(*object, Object::PropertyKind::Key, true); for (auto& property_name : property_names.as_object().indexed_properties()) { - interpreter.set_variable(variable_name, property_name.value_and_attributes(object).value, global_object); + interpreter.vm().set_variable(variable_name, property_name.value_and_attributes(object).value, global_object); if (interpreter.exception()) return {}; - last_value = interpreter.execute_statement(global_object, *m_body); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) { - if (interpreter.should_unwind_until(ScopeType::Continuable, m_label)) { - interpreter.stop_unwind(); - } else if (interpreter.should_unwind_until(ScopeType::Breakable, m_label)) { - interpreter.stop_unwind(); + if (interpreter.vm().should_unwind()) { + if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) { + interpreter.vm().stop_unwind(); + } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) { + interpreter.vm().stop_unwind(); break; } else { return js_undefined(); @@ -425,7 +425,7 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj auto variable_name = variable_from_for_declaration(interpreter, global_object, m_lhs, wrapper); auto wrapper_cleanup = ScopeGuard([&] { if (wrapper) - interpreter.exit_scope(*wrapper); + interpreter.vm().exit_scope(*wrapper); }); auto last_value = js_undefined(); auto rhs_result = m_rhs->execute(interpreter, global_object); @@ -433,15 +433,15 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj return {}; get_iterator_values(global_object, rhs_result, [&](Value value) { - interpreter.set_variable(variable_name, value, global_object); - last_value = interpreter.execute_statement(global_object, *m_body); + interpreter.vm().set_variable(variable_name, value, global_object); + last_value = interpreter.vm().execute_statement(global_object, *m_body); if (interpreter.exception()) return IterationDecision::Break; - if (interpreter.should_unwind()) { - if (interpreter.should_unwind_until(ScopeType::Continuable, m_label)) { - interpreter.stop_unwind(); - } else if (interpreter.should_unwind_until(ScopeType::Breakable, m_label)) { - interpreter.stop_unwind(); + if (interpreter.vm().should_unwind()) { + if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) { + interpreter.vm().stop_unwind(); + } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) { + interpreter.vm().stop_unwind(); return IterationDecision::Break; } else { return IterationDecision::Break; @@ -453,7 +453,7 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) + if (interpreter.vm().should_unwind()) return js_undefined(); return last_value; } @@ -560,7 +560,7 @@ Reference Expression::to_reference(Interpreter&, GlobalObject&) const Reference Identifier::to_reference(Interpreter& interpreter, GlobalObject&) const { - return interpreter.get_reference(string()); + return interpreter.vm().get_reference(string()); } Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject& global_object) const @@ -601,7 +601,7 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob // FIXME: standard recommends checking with is_unresolvable but it ALWAYS return false here if (reference.is_local_variable() || reference.is_global_variable()) { auto name = reference.name(); - lhs_result = interpreter.get_variable(name.to_string(), global_object).value_or(js_undefined()); + lhs_result = interpreter.vm().get_variable(name.to_string(), global_object).value_or(js_undefined()); if (interpreter.exception()) return {}; } @@ -684,7 +684,7 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob if (interpreter.exception()) return {}; if (!super_constructor.is_function() && !super_constructor.is_null()) { - interpreter.throw_exception(ErrorType::ClassDoesNotExtendAConstructorOrNull, super_constructor.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::ClassDoesNotExtendAConstructorOrNull, super_constructor.to_string_without_side_effects().characters()); return {}; } class_constructor->set_constructor_kind(Function::ConstructorKind::Derived); @@ -712,7 +712,7 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob return {}; if (!class_prototype.is_object()) { - interpreter.throw_exception(ErrorType::NotAnObject, "Class prototype"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAnObject, "Class prototype"); return {}; } for (const auto& method : m_methods) { @@ -1153,9 +1153,9 @@ void ForOfStatement::dump(int indent) const Value Identifier::execute(Interpreter& interpreter, GlobalObject& global_object) const { - auto value = interpreter.get_variable(string(), global_object); + auto value = interpreter.vm().get_variable(string(), global_object); if (value.is_empty()) { - interpreter.throw_exception(ErrorType::UnknownIdentifier, string().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::UnknownIdentifier, string().characters()); return {}; } return value; @@ -1180,7 +1180,7 @@ Value SpreadExpression::execute(Interpreter& interpreter, GlobalObject& global_o Value ThisExpression::execute(Interpreter& interpreter, GlobalObject&) const { - return interpreter.resolve_this_binding(); + return interpreter.vm().resolve_this_binding(); } void ThisExpression::dump(int indent) const @@ -1279,7 +1279,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob return {}; if (reference.is_unresolvable()) { - interpreter.throw_exception(ErrorType::InvalidLeftHandAssignment); + interpreter.vm().throw_exception(global_object, ErrorType::InvalidLeftHandAssignment); return {}; } update_function_name(rhs_result, get_function_name(interpreter, reference.name().to_value(interpreter))); @@ -1410,7 +1410,7 @@ Value VariableDeclaration::execute(Interpreter& interpreter, GlobalObject& globa return {}; auto variable_name = declarator.id().string(); update_function_name(initalizer_result, variable_name); - interpreter.set_variable(variable_name, initalizer_result, global_object, true); + interpreter.vm().set_variable(variable_name, initalizer_result, global_object, true); } } return js_undefined(); @@ -1723,7 +1723,7 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& glo if (interpreter.exception()) return {}; if (!tag.is_function()) { - interpreter.throw_exception(ErrorType::NotAFunction, tag.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NotAFunction, tag.to_string_without_side_effects().characters()); return {}; } auto& tag_function = tag.as_function(); @@ -1793,12 +1793,12 @@ void ThrowStatement::dump(int indent) const Value TryStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const { - interpreter.execute_statement(global_object, m_block, {}, ScopeType::Try); + interpreter.vm().execute_statement(global_object, m_block, {}, ScopeType::Try); if (auto* exception = interpreter.exception()) { if (m_handler) { interpreter.vm().clear_exception(); ArgumentVector arguments { { m_handler->parameter(), exception->value() } }; - interpreter.execute_statement(global_object, m_handler->body(), move(arguments)); + interpreter.vm().execute_statement(global_object, m_handler->body(), move(arguments)); } } @@ -1807,14 +1807,14 @@ Value TryStatement::execute(Interpreter& interpreter, GlobalObject& global_objec // execute() the finalizer without an exception in our way. auto* previous_exception = interpreter.exception(); interpreter.vm().clear_exception(); - interpreter.stop_unwind(); + interpreter.vm().stop_unwind(); m_finalizer->execute(interpreter, global_object); // If we previously had an exception and the finalizer didn't // throw a new one, restore the old one. // FIXME: This will print debug output in throw_exception() for // a seconds time with INTERPRETER_DEBUG enabled. if (previous_exception && !interpreter.exception()) - interpreter.throw_exception(previous_exception); + interpreter.vm().throw_exception(previous_exception); } return js_undefined(); @@ -1830,9 +1830,9 @@ Value CatchClause::execute(Interpreter&, GlobalObject&) const Value ThrowStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const { auto value = m_argument->execute(interpreter, global_object); - if (interpreter.exception()) + if (interpreter.vm().exception()) return {}; - interpreter.throw_exception(value); + interpreter.vm().throw_exception(global_object, value); return {}; } @@ -1858,9 +1858,9 @@ Value SwitchStatement::execute(Interpreter& interpreter, GlobalObject& global_ob statement.execute(interpreter, global_object); if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) { - if (interpreter.should_unwind_until(ScopeType::Breakable, m_label)) { - interpreter.stop_unwind(); + if (interpreter.vm().should_unwind()) { + if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) { + interpreter.vm().stop_unwind(); return {}; } return {}; @@ -1878,13 +1878,13 @@ Value SwitchCase::execute(Interpreter&, GlobalObject&) const Value BreakStatement::execute(Interpreter& interpreter, GlobalObject&) const { - interpreter.unwind(ScopeType::Breakable, m_target_label); + interpreter.vm().unwind(ScopeType::Breakable, m_target_label); return js_undefined(); } Value ContinueStatement::execute(Interpreter& interpreter, GlobalObject&) const { - interpreter.unwind(ScopeType::Continuable, m_target_label); + interpreter.vm().unwind(ScopeType::Continuable, m_target_label); return js_undefined(); } diff --git a/Libraries/LibJS/Console.cpp b/Libraries/LibJS/Console.cpp index cd40739ebc9..eff5bec2e93 100644 --- a/Libraries/LibJS/Console.cpp +++ b/Libraries/LibJS/Console.cpp @@ -123,7 +123,7 @@ bool Console::counter_reset(String label) Vector ConsoleClient::get_trace() const { Vector trace; - auto& call_stack = m_console.interpreter().call_stack(); + auto& call_stack = m_console.interpreter().vm().call_stack(); // -2 to skip the console.trace() call frame for (ssize_t i = call_stack.size() - 2; i >= 0; --i) trace.append(call_stack[i].function_name); diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 4309074129c..f000c425018 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -56,272 +56,22 @@ Interpreter::~Interpreter() Value Interpreter::run(GlobalObject& global_object, const Program& program) { - VM::InterpreterExecutionScope scope(*this); - - ASSERT(!exception()); - - if (m_call_stack.is_empty()) { - CallFrame global_call_frame; - global_call_frame.this_value = &global_object; - global_call_frame.function_name = "(global execution context)"; - global_call_frame.environment = heap().allocate(global_object, LexicalEnvironment::EnvironmentRecordType::Global); - global_call_frame.environment->bind_this_value(&global_object); - if (exception()) - return {}; - m_call_stack.append(move(global_call_frame)); - } - - return program.execute(*this, global_object); -} - -Value Interpreter::execute_statement(GlobalObject& global_object, const Statement& statement, ArgumentVector arguments, ScopeType scope_type) -{ - if (!statement.is_scope_node()) - return statement.execute(*this, global_object); - - auto& block = static_cast(statement); - enter_scope(block, move(arguments), scope_type, global_object); - - if (block.children().is_empty()) - m_last_value = js_undefined(); - - for (auto& node : block.children()) { - m_last_value = node.execute(*this, global_object); - if (should_unwind()) { - if (!block.label().is_null() && should_unwind_until(ScopeType::Breakable, block.label())) - stop_unwind(); - break; - } - } - - bool did_return = m_unwind_until == ScopeType::Function; - - if (m_unwind_until == scope_type) - m_unwind_until = ScopeType::None; - - exit_scope(block); - - return did_return ? m_last_value : js_undefined(); -} - -void Interpreter::enter_scope(const ScopeNode& scope_node, ArgumentVector arguments, ScopeType scope_type, GlobalObject& global_object) -{ - for (auto& declaration : scope_node.functions()) { - auto* function = ScriptFunction::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), current_environment()); - set_variable(declaration.name(), function, global_object); - } - - if (scope_type == ScopeType::Function) { - m_scope_stack.append({ scope_type, scope_node, false }); - return; - } - - HashMap scope_variables_with_declaration_kind; - scope_variables_with_declaration_kind.ensure_capacity(16); - - for (auto& declaration : scope_node.variables()) { - for (auto& declarator : declaration.declarations()) { - if (scope_node.is_program()) { - global_object.put(declarator.id().string(), js_undefined()); - if (exception()) - return; - } else { - scope_variables_with_declaration_kind.set(declarator.id().string(), { js_undefined(), declaration.declaration_kind() }); - } - } - } - - for (auto& argument : arguments) { - scope_variables_with_declaration_kind.set(argument.name, { argument.value, DeclarationKind::Var }); - } - - bool pushed_lexical_environment = false; - - if (!scope_variables_with_declaration_kind.is_empty()) { - auto* block_lexical_environment = heap().allocate(global_object, move(scope_variables_with_declaration_kind), current_environment()); - m_call_stack.last().environment = block_lexical_environment; - pushed_lexical_environment = true; - } - - m_scope_stack.append({ scope_type, scope_node, pushed_lexical_environment }); -} - -void Interpreter::exit_scope(const ScopeNode& scope_node) -{ - while (!m_scope_stack.is_empty()) { - auto popped_scope = m_scope_stack.take_last(); - if (popped_scope.pushed_environment) - m_call_stack.last().environment = m_call_stack.last().environment->parent(); - if (popped_scope.scope_node.ptr() == &scope_node) - break; - } - - // If we unwind all the way, just reset m_unwind_until so that future "return" doesn't break. - if (m_scope_stack.is_empty()) - m_unwind_until = ScopeType::None; -} - -void Interpreter::set_variable(const FlyString& name, Value value, GlobalObject& global_object, bool first_assignment) -{ - if (m_call_stack.size()) { - for (auto* environment = current_environment(); environment; environment = environment->parent()) { - auto possible_match = environment->get(name); - if (possible_match.has_value()) { - if (!first_assignment && possible_match.value().declaration_kind == DeclarationKind::Const) { - throw_exception(ErrorType::InvalidAssignToConst); - return; - } - - environment->set(name, { value, possible_match.value().declaration_kind }); - return; - } - } - } - - global_object.put(move(name), move(value)); -} - -Value Interpreter::get_variable(const FlyString& name, GlobalObject& global_object) -{ - if (m_call_stack.size()) { - for (auto* environment = current_environment(); environment; environment = environment->parent()) { - auto possible_match = environment->get(name); - if (possible_match.has_value()) - return possible_match.value().value; - } - } - auto value = global_object.get(name); - if (m_underscore_is_last_value && name == "_" && value.is_empty()) - return m_last_value; - return value; -} - -Reference Interpreter::get_reference(const FlyString& name) -{ - if (m_call_stack.size()) { - for (auto* environment = current_environment(); environment; environment = environment->parent()) { - auto possible_match = environment->get(name); - if (possible_match.has_value()) - return { Reference::LocalVariable, name }; - } - } - return { Reference::GlobalVariable, name }; -} - -void Interpreter::gather_roots(HashTable& roots) -{ - if (m_last_value.is_cell()) - roots.set(m_last_value.as_cell()); - - for (auto& call_frame : m_call_stack) { - if (call_frame.this_value.is_cell()) - roots.set(call_frame.this_value.as_cell()); - for (auto& argument : call_frame.arguments) { - if (argument.is_cell()) - roots.set(argument.as_cell()); - } - roots.set(call_frame.environment); - } -} - -Value Interpreter::call_internal(Function& function, Value this_value, Optional arguments) -{ - ASSERT(!exception()); + ASSERT(!vm().exception()); VM::InterpreterExecutionScope scope(*this); - auto& call_frame = push_call_frame(); - call_frame.function_name = function.name(); - call_frame.this_value = function.bound_this().value_or(this_value); - call_frame.arguments = function.bound_arguments(); - if (arguments.has_value()) - call_frame.arguments.append(arguments.value().values()); - call_frame.environment = function.create_environment(); - - ASSERT(call_frame.environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized); - call_frame.environment->bind_this_value(call_frame.this_value); - - auto result = function.call(*this); - pop_call_frame(); - return result; -} - -Value Interpreter::construct(Function& function, Function& new_target, Optional arguments, GlobalObject& global_object) -{ - auto& call_frame = push_call_frame(); - call_frame.function_name = function.name(); - call_frame.arguments = function.bound_arguments(); - if (arguments.has_value()) - call_frame.arguments.append(arguments.value().values()); - call_frame.environment = function.create_environment(); - - current_environment()->set_new_target(&new_target); - - Object* new_object = nullptr; - if (function.constructor_kind() == Function::ConstructorKind::Base) { - new_object = Object::create_empty(global_object); - current_environment()->bind_this_value(new_object); - if (exception()) - return {}; - auto prototype = new_target.get("prototype"); - if (exception()) - return {}; - if (prototype.is_object()) { - new_object->set_prototype(&prototype.as_object()); - if (exception()) - return {}; - } - } - - // If we are a Derived constructor, |this| has not been constructed before super is called. - Value this_value = function.constructor_kind() == Function::ConstructorKind::Base ? new_object : Value {}; - call_frame.this_value = this_value; - auto result = function.construct(*this, new_target); - - this_value = current_environment()->get_this_binding(); - pop_call_frame(); - - // If we are constructing an instance of a derived class, - // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses). - if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) { - current_environment()->replace_this_binding(result); - auto prototype = new_target.get("prototype"); - if (exception()) - return {}; - if (prototype.is_object()) { - result.as_object().set_prototype(&prototype.as_object()); - if (exception()) - return {}; - } - return result; - } - - if (exception()) + CallFrame global_call_frame; + global_call_frame.this_value = &global_object; + global_call_frame.function_name = "(global execution context)"; + global_call_frame.environment = heap().allocate(global_object, LexicalEnvironment::EnvironmentRecordType::Global); + global_call_frame.environment->bind_this_value(&global_object); + if (vm().exception()) return {}; + vm().call_stack().append(move(global_call_frame)); - if (result.is_object()) - return result; - - return this_value; -} - -void Interpreter::throw_exception(Exception* exception) -{ -#ifdef INTERPRETER_DEBUG - if (exception->value().is_object() && exception->value().as_object().is_error()) { - auto& error = static_cast(exception->value().as_object()); - dbg() << "Throwing JavaScript Error: " << error.name() << ", " << error.message(); - - for (ssize_t i = m_call_stack.size() - 1; i >= 0; --i) { - auto function_name = m_call_stack[i].function_name; - if (function_name.is_empty()) - function_name = ""; - dbg() << " " << function_name; - } - } -#endif - vm().set_exception({}, exception); - unwind(ScopeType::Try); + auto result = program.execute(*this, global_object); + vm().pop_call_frame(); + return result; } GlobalObject& Interpreter::global_object() @@ -334,35 +84,26 @@ const GlobalObject& Interpreter::global_object() const return static_cast(*m_global_object.cell()); } -String Interpreter::join_arguments() const +Value Interpreter::call_internal(Function& function, Value this_value, Optional arguments) { - StringBuilder joined_arguments; - for (size_t i = 0; i < argument_count(); ++i) { - joined_arguments.append(argument(i).to_string_without_side_effects().characters()); - if (i != argument_count() - 1) - joined_arguments.append(' '); - } - return joined_arguments.build(); -} + ASSERT(!exception()); -Value Interpreter::resolve_this_binding() const -{ - return get_this_environment()->get_this_binding(); -} + VM::InterpreterExecutionScope scope(*this); -const LexicalEnvironment* Interpreter::get_this_environment() const -{ - // We will always return because the Global environment will always be reached, which has a |this| binding. - for (const LexicalEnvironment* environment = current_environment(); environment; environment = environment->parent()) { - if (environment->has_this_binding()) - return environment; - } - ASSERT_NOT_REACHED(); -} + auto& call_frame = vm().push_call_frame(); + call_frame.function_name = function.name(); + call_frame.this_value = function.bound_this().value_or(this_value); + call_frame.arguments = function.bound_arguments(); + if (arguments.has_value()) + call_frame.arguments.append(arguments.value().values()); + call_frame.environment = function.create_environment(); -Value Interpreter::get_new_target() const -{ - return get_this_environment()->new_target(); + ASSERT(call_frame.environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized); + call_frame.environment->bind_this_value(call_frame.this_value); + + auto result = function.call(*this); + vm().pop_call_frame(); + return result; } } diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 6ba52bc5a38..8d8b40acb2b 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -45,35 +45,6 @@ namespace JS { -enum class ScopeType { - None, - Function, - Block, - Try, - Breakable, - Continuable, -}; - -struct ScopeFrame { - ScopeType type; - NonnullRefPtr scope_node; - bool pushed_environment { false }; -}; - -struct CallFrame { - FlyString function_name; - Value this_value; - Vector arguments; - LexicalEnvironment* environment { nullptr }; -}; - -struct Argument { - FlyString name; - Value value; -}; - -typedef Vector ArgumentVector; - class Interpreter : public Weakable { public: template @@ -106,122 +77,23 @@ public: Value run(GlobalObject&, const Program&); - Value execute_statement(GlobalObject&, const Statement&, ArgumentVector = {}, ScopeType = ScopeType::Block); - GlobalObject& global_object(); const GlobalObject& global_object() const; VM& vm() { return *m_vm; } + const VM& vm() const { return *m_vm; } Heap& heap() { return vm().heap(); } Exception* exception() { return vm().exception(); } - void unwind(ScopeType type, FlyString label = {}) - { - m_unwind_until = type; - m_unwind_until_label = label; - } - void stop_unwind() { m_unwind_until = ScopeType::None; } - bool should_unwind_until(ScopeType type, FlyString label) const - { - if (m_unwind_until_label.is_null()) - return m_unwind_until == type; - return m_unwind_until == type && m_unwind_until_label == label; - } - bool should_unwind() const { return m_unwind_until != ScopeType::None; } - - Value get_variable(const FlyString& name, GlobalObject&); - void set_variable(const FlyString& name, Value, GlobalObject&, bool first_assignment = false); - - Reference get_reference(const FlyString& name); - - void gather_roots(HashTable&); - - void enter_scope(const ScopeNode&, ArgumentVector, ScopeType, GlobalObject&); - void exit_scope(const ScopeNode&); - - Value construct(Function&, Function& new_target, Optional arguments, GlobalObject&); - - CallFrame& push_call_frame() - { - m_call_stack.append({ {}, js_undefined(), {}, nullptr }); - return m_call_stack.last(); - } - void pop_call_frame() { m_call_stack.take_last(); } - const CallFrame& call_frame() { return m_call_stack.last(); } - const Vector& call_stack() { return m_call_stack; } - - const LexicalEnvironment* current_environment() const { return m_call_stack.last().environment; } - LexicalEnvironment* current_environment() { return m_call_stack.last().environment; } - - bool in_strict_mode() const - { - if (m_scope_stack.is_empty()) - return true; - return m_scope_stack.last().scope_node->in_strict_mode(); - } - - template - void for_each_argument(Callback callback) - { - if (m_call_stack.is_empty()) - return; - for (auto& value : m_call_stack.last().arguments) - callback(value); - } - - size_t argument_count() const - { - if (m_call_stack.is_empty()) - return 0; - return m_call_stack.last().arguments.size(); - } - - Value argument(size_t index) const - { - if (m_call_stack.is_empty()) - return {}; - auto& arguments = m_call_stack.last().arguments; - return index < arguments.size() ? arguments[index] : js_undefined(); - } - - Value this_value(Object& global_object) const - { - if (m_call_stack.is_empty()) - return &global_object; - return m_call_stack.last().this_value; - } - - template - void throw_exception(Args&&... args) - { - return throw_exception(T::create(global_object(), forward(args)...)); - } - - void throw_exception(Exception*); - void throw_exception(Value value) - { - return throw_exception(heap().allocate(global_object(), value)); - } - - template - void throw_exception(ErrorType type, Args&&... args) - { - return throw_exception(T::create(global_object(), String::format(type.message(), forward(args)...))); - } - - Value last_value() const { return m_last_value; } - - bool underscore_is_last_value() const { return m_underscore_is_last_value; } - void set_underscore_is_last_value(bool b) { m_underscore_is_last_value = b; } - Console& console() { return m_console; } const Console& console() const { return m_console; } - String join_arguments() const; - - Value resolve_this_binding() const; - const LexicalEnvironment* get_this_environment() const; - Value get_new_target() const; + bool in_strict_mode() const { return vm().in_strict_mode(); } + size_t argument_count() const { return vm().argument_count(); } + Value argument(size_t index) const { return vm().argument(index); } + Value this_value(Object& global_object) const { return vm().this_value(global_object); } + LexicalEnvironment* current_environment() { return vm().current_environment(); } + const CallFrame& call_frame() { return vm().call_frame(); } private: explicit Interpreter(VM&); @@ -230,18 +102,8 @@ private: NonnullRefPtr m_vm; - Value m_last_value; - - Vector m_scope_stack; - Vector m_call_stack; - Handle m_global_object; - ScopeType m_unwind_until { ScopeType::None }; - FlyString m_unwind_until_label; - - bool m_underscore_is_last_value { false }; - Console m_console; }; diff --git a/Libraries/LibJS/Runtime/Array.cpp b/Libraries/LibJS/Runtime/Array.cpp index 98948de0cae..0a0ac53b63e 100644 --- a/Libraries/LibJS/Runtime/Array.cpp +++ b/Libraries/LibJS/Runtime/Array.cpp @@ -55,7 +55,7 @@ Array* Array::typed_this(Interpreter& interpreter, GlobalObject& global_object) if (!this_object) return {}; if (!this_object->is_array()) { - interpreter.throw_exception(ErrorType::NotAn, "Array"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAn, "Array"); return nullptr; } return static_cast(this_object); @@ -78,7 +78,7 @@ JS_DEFINE_NATIVE_SETTER(Array::length_setter) if (interpreter.exception()) return; if (length.is_nan() || length.is_infinity() || length.as_double() < 0) { - interpreter.throw_exception(ErrorType::ArrayInvalidLength); + interpreter.vm().throw_exception(global_object, ErrorType::ArrayInvalidLength); return; } array->indexed_properties().set_array_like_size(length.as_double()); diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 951c0998a19..d0785fa4dab 100644 --- a/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -67,7 +67,7 @@ Value ArrayConstructor::call(Interpreter& interpreter) if (interpreter.argument_count() == 1 && interpreter.argument(0).is_number()) { auto array_length_value = interpreter.argument(0); if (!array_length_value.is_integer() || array_length_value.as_i32() < 0) { - interpreter.throw_exception(ErrorType::ArrayInvalidLength); + interpreter.vm().throw_exception(global_object(), ErrorType::ArrayInvalidLength); return {}; } auto* array = Array::create(global_object()); diff --git a/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp b/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp index 7e50923b96f..62b74000983 100644 --- a/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp @@ -54,7 +54,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayIteratorPrototype::next) { auto this_value = interpreter.this_value(global_object); if (!this_value.is_object() || !this_value.as_object().is_array_iterator_object()) { - interpreter.throw_exception(ErrorType::NotAn, "Array Iterator"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAn, "Array Iterator"); return {}; } auto& this_object = this_value.as_object(); diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index d30eff31d2c..fac4b742c66 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -90,12 +90,12 @@ ArrayPrototype::~ArrayPrototype() static Function* callback_from_args(Interpreter& interpreter, const String& name) { if (interpreter.argument_count() < 1) { - interpreter.throw_exception(ErrorType::ArrayPrototypeOneArg, name.characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::ArrayPrototypeOneArg, name.characters()); return nullptr; } auto callback = interpreter.argument(0); if (!callback.is_function()) { - interpreter.throw_exception(ErrorType::NotAFunction, callback.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::NotAFunction, callback.to_string_without_side_effects().characters()); return nullptr; } return &callback.as_function(); @@ -199,7 +199,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push) auto argument_count = interpreter.argument_count(); auto new_length = length + argument_count; if (new_length > MAX_ARRAY_LIKE_INDEX) { - interpreter.throw_exception(ErrorType::ArrayMaxSize); + interpreter.vm().throw_exception(global_object, ErrorType::ArrayMaxSize); return {}; } for (size_t i = 0; i < argument_count; ++i) { @@ -474,7 +474,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce) start += 1; } if (!start_found) { - interpreter.throw_exception(ErrorType::ReduceNoInitial); + interpreter.vm().throw_exception(global_object, ErrorType::ReduceNoInitial); return {}; } } @@ -527,7 +527,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right) start -= 1; } if (!start_found) { - interpreter.throw_exception(ErrorType::ReduceNoInitial); + interpreter.vm().throw_exception(global_object, ErrorType::ReduceNoInitial); return {}; } } @@ -729,7 +729,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice) size_t new_length = initial_length + insert_count - actual_delete_count; if (new_length > MAX_ARRAY_LIKE_INDEX) { - interpreter.throw_exception(ErrorType::ArrayMaxSize); + interpreter.vm().throw_exception(global_object, ErrorType::ArrayMaxSize); return {}; } diff --git a/Libraries/LibJS/Runtime/BigIntConstructor.cpp b/Libraries/LibJS/Runtime/BigIntConstructor.cpp index 8eed34a1a70..198c6179e9d 100644 --- a/Libraries/LibJS/Runtime/BigIntConstructor.cpp +++ b/Libraries/LibJS/Runtime/BigIntConstructor.cpp @@ -61,7 +61,7 @@ Value BigIntConstructor::call(Interpreter& interpreter) return {}; if (primitive.is_number()) { if (!primitive.is_integer()) { - interpreter.throw_exception(ErrorType::BigIntIntArgument); + interpreter.vm().throw_exception(global_object(), ErrorType::BigIntIntArgument); return {}; } return js_bigint(interpreter, Crypto::SignedBigInteger { primitive.as_i32() }); @@ -74,7 +74,7 @@ Value BigIntConstructor::call(Interpreter& interpreter) Value BigIntConstructor::construct(Interpreter& interpreter, Function&) { - interpreter.throw_exception(ErrorType::NotAConstructor, "BigInt"); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAConstructor, "BigInt"); return {}; } diff --git a/Libraries/LibJS/Runtime/BigIntPrototype.cpp b/Libraries/LibJS/Runtime/BigIntPrototype.cpp index eb2ddc0c170..b2e28bc5ef5 100644 --- a/Libraries/LibJS/Runtime/BigIntPrototype.cpp +++ b/Libraries/LibJS/Runtime/BigIntPrototype.cpp @@ -58,7 +58,7 @@ static BigIntObject* bigint_object_from(Interpreter& interpreter, GlobalObject& if (!this_object) return nullptr; if (!this_object->is_bigint_object()) { - interpreter.throw_exception(ErrorType::NotA, "BigInt"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "BigInt"); return nullptr; } return static_cast(this_object); diff --git a/Libraries/LibJS/Runtime/BooleanPrototype.cpp b/Libraries/LibJS/Runtime/BooleanPrototype.cpp index 8d99679fd14..cadc070dfe3 100644 --- a/Libraries/LibJS/Runtime/BooleanPrototype.cpp +++ b/Libraries/LibJS/Runtime/BooleanPrototype.cpp @@ -55,7 +55,7 @@ JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::to_string) return js_string(interpreter.heap(), this_object.as_bool() ? "true" : "false"); } if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) { - interpreter.throw_exception(ErrorType::NotA, "Boolean"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Boolean"); return {}; } @@ -70,7 +70,7 @@ JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::value_of) return this_object; } if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) { - interpreter.throw_exception(ErrorType::NotA, "Boolean"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Boolean"); return {}; } diff --git a/Libraries/LibJS/Runtime/DatePrototype.cpp b/Libraries/LibJS/Runtime/DatePrototype.cpp index 3bc83519670..e3c54e24df1 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -42,7 +42,7 @@ static Date* typed_this(Interpreter& interpreter, GlobalObject& global_object) if (!this_object) return nullptr; if (!this_object->is_date()) { - interpreter.throw_exception(ErrorType::NotA, "Date"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Date"); return nullptr; } return static_cast(this_object); diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.cpp b/Libraries/LibJS/Runtime/ErrorPrototype.cpp index 867dee87745..baf213f2247 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.cpp +++ b/Libraries/LibJS/Runtime/ErrorPrototype.cpp @@ -59,7 +59,7 @@ JS_DEFINE_NATIVE_GETTER(ErrorPrototype::name_getter) if (!this_object) return {}; if (!this_object->is_error()) { - interpreter.throw_exception(ErrorType::NotAn, "Error"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAn, "Error"); return {}; } return js_string(interpreter, static_cast(this_object)->name()); @@ -71,7 +71,7 @@ JS_DEFINE_NATIVE_SETTER(ErrorPrototype::name_setter) if (!this_object) return; if (!this_object->is_error()) { - interpreter.throw_exception(ErrorType::NotAn, "Error"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAn, "Error"); return; } auto name = value.to_string(interpreter); @@ -86,7 +86,7 @@ JS_DEFINE_NATIVE_GETTER(ErrorPrototype::message_getter) if (!this_object) return {}; if (!this_object->is_error()) { - interpreter.throw_exception(ErrorType::NotAn, "Error"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAn, "Error"); return {}; } return js_string(interpreter, static_cast(this_object)->message()); @@ -95,7 +95,7 @@ JS_DEFINE_NATIVE_GETTER(ErrorPrototype::message_getter) JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string) { if (!interpreter.this_value(global_object).is_object()) { - interpreter.throw_exception(ErrorType::NotAnObject, interpreter.this_value(global_object).to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NotAnObject, interpreter.this_value(global_object).to_string_without_side_effects().characters()); return {}; } auto& this_object = interpreter.this_value(global_object).as_object(); diff --git a/Libraries/LibJS/Runtime/Exception.cpp b/Libraries/LibJS/Runtime/Exception.cpp index a92ec65c2bd..190d9c421d8 100644 --- a/Libraries/LibJS/Runtime/Exception.cpp +++ b/Libraries/LibJS/Runtime/Exception.cpp @@ -32,7 +32,7 @@ namespace JS { Exception::Exception(Value value) : m_value(value) { - auto& call_stack = interpreter().call_stack(); + auto& call_stack = vm().call_stack(); for (ssize_t i = call_stack.size() - 1; i >= 0; --i) { auto function_name = call_stack[i].function_name; if (function_name.is_empty()) diff --git a/Libraries/LibJS/Runtime/Exception.h b/Libraries/LibJS/Runtime/Exception.h index 2d9f23d01ac..76ff86e71f4 100644 --- a/Libraries/LibJS/Runtime/Exception.h +++ b/Libraries/LibJS/Runtime/Exception.h @@ -26,6 +26,7 @@ #pragma once +#include #include #include diff --git a/Libraries/LibJS/Runtime/FunctionConstructor.cpp b/Libraries/LibJS/Runtime/FunctionConstructor.cpp index 5af0bfd5a50..861f3c13ea0 100644 --- a/Libraries/LibJS/Runtime/FunctionConstructor.cpp +++ b/Libraries/LibJS/Runtime/FunctionConstructor.cpp @@ -84,7 +84,7 @@ Value FunctionConstructor::construct(Interpreter& interpreter, Function&) auto function_expression = parser.parse_function_node(); if (parser.has_errors()) { auto error = parser.errors()[0]; - interpreter.throw_exception(error.to_string()); + interpreter.vm().throw_exception(global_object(), error.to_string()); return {}; } return function_expression->execute(interpreter, global_object()); diff --git a/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Libraries/LibJS/Runtime/FunctionPrototype.cpp index f96fbcece7b..dc3d5f5489e 100644 --- a/Libraries/LibJS/Runtime/FunctionPrototype.cpp +++ b/Libraries/LibJS/Runtime/FunctionPrototype.cpp @@ -66,7 +66,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply) if (!this_object) return {}; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotA, "Function"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Function"); return {}; } auto& function = static_cast(*this_object); @@ -75,7 +75,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply) if (arg_array.is_null() || arg_array.is_undefined()) return interpreter.call(function, this_arg); if (!arg_array.is_object()) { - interpreter.throw_exception(ErrorType::FunctionArgsNotObject); + interpreter.vm().throw_exception(global_object, ErrorType::FunctionArgsNotObject); return {}; } auto length_property = arg_array.as_object().get("length"); @@ -100,7 +100,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind) if (!this_object) return {}; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotA, "Function"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Function"); return {}; } auto& this_function = static_cast(*this_object); @@ -121,7 +121,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call) if (!this_object) return {}; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotA, "Function"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Function"); return {}; } auto& function = static_cast(*this_object); @@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string) if (!this_object) return {}; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotA, "Function"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Function"); return {}; } String function_name = static_cast(this_object)->name(); @@ -182,7 +182,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::symbol_has_instance) if (!this_object) return {}; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotA, "Function"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Function"); return {}; } return ordinary_has_instance(interpreter, interpreter.argument(0), this_object); diff --git a/Libraries/LibJS/Runtime/IteratorOperations.cpp b/Libraries/LibJS/Runtime/IteratorOperations.cpp index 1cb821577e7..c662521add6 100644 --- a/Libraries/LibJS/Runtime/IteratorOperations.cpp +++ b/Libraries/LibJS/Runtime/IteratorOperations.cpp @@ -46,14 +46,14 @@ Object* get_iterator(GlobalObject& global_object, Value value, String hint, Valu return {}; } if (!method.is_function()) { - interpreter.throw_exception(ErrorType::NotIterable, value.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NotIterable, value.to_string_without_side_effects().characters()); return nullptr; } auto iterator = interpreter.call(method.as_function(), value); if (interpreter.exception()) return {}; if (!iterator.is_object()) { - interpreter.throw_exception(ErrorType::NotIterable, value.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NotIterable, value.to_string_without_side_effects().characters()); return nullptr; } return &iterator.as_object(); @@ -62,12 +62,13 @@ Object* get_iterator(GlobalObject& global_object, Value value, String hint, Valu Object* iterator_next(Object& iterator, Value value) { auto& interpreter = iterator.interpreter(); + auto& global_object = iterator.global_object(); auto next_method = iterator.get("next"); if (interpreter.exception()) return {}; if (!next_method.is_function()) { - interpreter.throw_exception(ErrorType::IterableNextNotAFunction); + interpreter.vm().throw_exception(global_object, ErrorType::IterableNextNotAFunction); return nullptr; } @@ -80,7 +81,7 @@ Object* iterator_next(Object& iterator, Value value) if (interpreter.exception()) return {}; if (!result.is_object()) { - interpreter.throw_exception(ErrorType::IterableNextBadReturn); + interpreter.vm().throw_exception(global_object, ErrorType::IterableNextBadReturn); return nullptr; } diff --git a/Libraries/LibJS/Runtime/JSONObject.cpp b/Libraries/LibJS/Runtime/JSONObject.cpp index 183e814bbe2..38120be3eb9 100644 --- a/Libraries/LibJS/Runtime/JSONObject.cpp +++ b/Libraries/LibJS/Runtime/JSONObject.cpp @@ -192,14 +192,14 @@ String JSONObject::serialize_json_property(Interpreter& interpreter, StringifySt return serialize_json_object(interpreter, state, value.as_object()); } if (value.is_bigint()) - interpreter.throw_exception(ErrorType::JsonBigInt); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::JsonBigInt); return {}; } String JSONObject::serialize_json_object(Interpreter& interpreter, StringifyState& state, Object& object) { if (state.seen_objects.contains(&object)) { - interpreter.throw_exception(ErrorType::JsonCircular); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::JsonCircular); return {}; } @@ -282,7 +282,7 @@ String JSONObject::serialize_json_object(Interpreter& interpreter, StringifyStat String JSONObject::serialize_json_array(Interpreter& interpreter, StringifyState& state, Object& object) { if (state.seen_objects.contains(&object)) { - interpreter.throw_exception(ErrorType::JsonCircular); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::JsonCircular); return {}; } @@ -394,7 +394,7 @@ JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse) auto json = JsonValue::from_string(string); if (!json.has_value()) { - interpreter.throw_exception(ErrorType::JsonMalformed); + interpreter.vm().throw_exception(global_object, ErrorType::JsonMalformed); return {}; } Value result = parse_json_value(interpreter, global_object, json.value()); diff --git a/Libraries/LibJS/Runtime/LexicalEnvironment.cpp b/Libraries/LibJS/Runtime/LexicalEnvironment.cpp index 813e52ddf5a..470f8ba6eed 100644 --- a/Libraries/LibJS/Runtime/LexicalEnvironment.cpp +++ b/Libraries/LibJS/Runtime/LexicalEnvironment.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -72,12 +73,16 @@ void LexicalEnvironment::visit_children(Visitor& visitor) Optional LexicalEnvironment::get(const FlyString& name) const { + ASSERT(type() != EnvironmentRecordType::Global); return m_variables.get(name); } void LexicalEnvironment::set(const FlyString& name, Variable variable) { - m_variables.set(name, variable); + if (type() == EnvironmentRecordType::Global) + interpreter().global_object().put(name, variable.value); + else + m_variables.set(name, variable); } bool LexicalEnvironment::has_super_binding() const @@ -113,7 +118,7 @@ Value LexicalEnvironment::get_this_binding() const { ASSERT(has_this_binding()); if (this_binding_status() == ThisBindingStatus::Uninitialized) { - interpreter().throw_exception(ErrorType::ThisHasNotBeenInitialized); + interpreter().vm().throw_exception(interpreter().global_object(), ErrorType::ThisHasNotBeenInitialized); return {}; } return m_this_value; @@ -123,7 +128,7 @@ void LexicalEnvironment::bind_this_value(Value this_value) { ASSERT(has_this_binding()); if (m_this_binding_status == ThisBindingStatus::Initialized) { - interpreter().throw_exception(ErrorType::ThisIsAlreadyInitialized); + interpreter().vm().throw_exception(interpreter().global_object(), ErrorType::ThisIsAlreadyInitialized); return; } m_this_value = this_value; diff --git a/Libraries/LibJS/Runtime/LexicalEnvironment.h b/Libraries/LibJS/Runtime/LexicalEnvironment.h index a4c9deda131..a6d2173f2c0 100644 --- a/Libraries/LibJS/Runtime/LexicalEnvironment.h +++ b/Libraries/LibJS/Runtime/LexicalEnvironment.h @@ -87,6 +87,8 @@ public: Function* current_function() const { return m_current_function; } void set_current_function(Function& function) { m_current_function = &function; } + EnvironmentRecordType type() const { return m_environment_record_type; } + private: virtual const char* class_name() const override { return "LexicalEnvironment"; } virtual void visit_children(Visitor&) override; diff --git a/Libraries/LibJS/Runtime/NumberPrototype.cpp b/Libraries/LibJS/Runtime/NumberPrototype.cpp index 5f2d92e8df9..dad115c058a 100644 --- a/Libraries/LibJS/Runtime/NumberPrototype.cpp +++ b/Libraries/LibJS/Runtime/NumberPrototype.cpp @@ -69,7 +69,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string) } else if (this_value.is_object() && this_value.as_object().is_number_object()) { number_value = static_cast(this_value.as_object()).value_of(); } else { - interpreter.throw_exception(ErrorType::NumberIncompatibleThis, "toString"); + interpreter.vm().throw_exception(global_object, ErrorType::NumberIncompatibleThis, "toString"); return {}; } @@ -82,7 +82,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string) } if (interpreter.exception() || radix < 2 || radix > 36) { - interpreter.throw_exception(ErrorType::InvalidRadix); + interpreter.vm().throw_exception(global_object, ErrorType::InvalidRadix); return {}; } diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index a77c78df958..9e9aaca8ca4 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -358,7 +358,7 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object& if (is_accessor_property) { if (descriptor.has_property("value") || descriptor.has_property("writable")) { if (throw_exceptions) - interpreter().throw_exception(ErrorType::AccessorValueOrWritable); + interpreter().vm().throw_exception(global_object(), ErrorType::AccessorValueOrWritable); return false; } @@ -375,14 +375,14 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object& if (getter.is_function()) { getter_function = &getter.as_function(); } else if (!getter.is_undefined()) { - interpreter().throw_exception(ErrorType::AccessorBadField, "get"); + interpreter().vm().throw_exception(global_object(), ErrorType::AccessorBadField, "get"); return false; } if (setter.is_function()) { setter_function = &setter.as_function(); } else if (!setter.is_undefined()) { - interpreter().throw_exception(ErrorType::AccessorBadField, "set"); + interpreter().vm().throw_exception(global_object(), ErrorType::AccessorBadField, "set"); return false; } @@ -465,7 +465,7 @@ bool Object::put_own_property(Object& this_object, const StringOrSymbol& propert dbg() << "Disallow define_property of non-extensible object"; #endif if (throw_exceptions && interpreter().in_strict_mode()) - interpreter().throw_exception(ErrorType::NonExtensibleDefine, property_name.to_display_string().characters()); + interpreter().vm().throw_exception(global_object(), ErrorType::NonExtensibleDefine, property_name.to_display_string().characters()); return false; } @@ -499,7 +499,7 @@ bool Object::put_own_property(Object& this_object, const StringOrSymbol& propert dbg() << "Disallow reconfig of non-configurable property"; #endif if (throw_exceptions) - interpreter().throw_exception(ErrorType::DescChangeNonConfigurable, property_name.to_display_string().characters()); + interpreter().vm().throw_exception(global_object(), ErrorType::DescChangeNonConfigurable, property_name.to_display_string().characters()); return false; } @@ -547,7 +547,7 @@ bool Object::put_own_property_by_index(Object& this_object, u32 property_index, dbg() << "Disallow define_property of non-extensible object"; #endif if (throw_exceptions && interpreter().in_strict_mode()) - interpreter().throw_exception(ErrorType::NonExtensibleDefine, property_index); + interpreter().vm().throw_exception(global_object(), ErrorType::NonExtensibleDefine, property_index); return false; } @@ -566,7 +566,7 @@ bool Object::put_own_property_by_index(Object& this_object, u32 property_index, dbg() << "Disallow reconfig of non-configurable property"; #endif if (throw_exceptions) - interpreter().throw_exception(ErrorType::DescChangeNonConfigurable, property_index); + interpreter().vm().throw_exception(global_object(), ErrorType::DescChangeNonConfigurable, property_index); return false; } @@ -843,7 +843,7 @@ Value Object::to_string() const auto& interpreter = const_cast(this)->interpreter(); auto to_string_result = interpreter.call(to_string_function, const_cast(this)); if (to_string_result.is_object()) - interpreter.throw_exception(ErrorType::Convert, "object", "string"); + interpreter.vm().throw_exception(global_object(), ErrorType::Convert, "object", "string"); if (interpreter.exception()) return {}; auto* string = to_string_result.to_primitive_string(interpreter); @@ -861,7 +861,7 @@ Value Object::invoke(const StringOrSymbol& property_name, Optional(ErrorType::NotAFunction, property.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAFunction, property.to_string_without_side_effects().characters()); return {}; } return interpreter.call(property.as_function(), this, move(arguments)); @@ -870,20 +870,20 @@ Value Object::invoke(const StringOrSymbol& property_name, Optional(ErrorType::ObjectSetPrototypeOfTwoArgs); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectSetPrototypeOfTwoArgs); return {}; } auto* object = interpreter.argument(0).to_object(interpreter, global_object); @@ -119,12 +119,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of) } else if (prototype_value.is_object()) { prototype = &prototype_value.as_object(); } else { - interpreter.throw_exception(ErrorType::ObjectPrototypeWrongType); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectPrototypeWrongType); return {}; } if (!object->set_prototype(prototype)) { if (!interpreter.exception()) - interpreter.throw_exception(ErrorType::ObjectSetPrototypeOfReturnedFalse); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse); return {}; } return object; @@ -145,7 +145,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions) return argument; if (!argument.as_object().prevent_extensions()) { if (!interpreter.exception()) - interpreter.throw_exception(ErrorType::ObjectPreventExtensionsReturnedFalse); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse); return {}; } return argument; @@ -165,11 +165,11 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptor) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_) { if (!interpreter.argument(0).is_object()) { - interpreter.throw_exception(ErrorType::NotAnObject, "Object argument"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAnObject, "Object argument"); return {}; } if (!interpreter.argument(2).is_object()) { - interpreter.throw_exception(ErrorType::NotAnObject, "Descriptor argument"); + interpreter.vm().throw_exception(global_object, ErrorType::NotAnObject, "Descriptor argument"); return {}; } auto& object = interpreter.argument(0).as_object(); @@ -180,9 +180,9 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_) if (!object.define_property(property_key, descriptor)) { if (!interpreter.exception()) { if (object.is_proxy_object()) { - interpreter.throw_exception(ErrorType::ObjectDefinePropertyReturnedFalse); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectDefinePropertyReturnedFalse); } else { - interpreter.throw_exception(ErrorType::NonExtensibleDefine, property_key.to_display_string().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NonExtensibleDefine, property_key.to_display_string().characters()); } } return {}; @@ -198,7 +198,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys) { if (!interpreter.argument_count()) { - interpreter.throw_exception(ErrorType::ConvertUndefinedToObject); + interpreter.vm().throw_exception(global_object, ErrorType::ConvertUndefinedToObject); return {}; } @@ -212,7 +212,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values) { if (!interpreter.argument_count()) { - interpreter.throw_exception(ErrorType::ConvertUndefinedToObject); + interpreter.vm().throw_exception(global_object, ErrorType::ConvertUndefinedToObject); return {}; } auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object); @@ -225,7 +225,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::entries) { if (!interpreter.argument_count()) { - interpreter.throw_exception(ErrorType::ConvertUndefinedToObject); + interpreter.vm().throw_exception(global_object, ErrorType::ConvertUndefinedToObject); return {}; } auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object); diff --git a/Libraries/LibJS/Runtime/ProxyConstructor.cpp b/Libraries/LibJS/Runtime/ProxyConstructor.cpp index c5b76307d52..d1c35803ceb 100644 --- a/Libraries/LibJS/Runtime/ProxyConstructor.cpp +++ b/Libraries/LibJS/Runtime/ProxyConstructor.cpp @@ -51,14 +51,14 @@ ProxyConstructor::~ProxyConstructor() Value ProxyConstructor::call(Interpreter& interpreter) { - interpreter.throw_exception(ErrorType::ProxyCallWithNew); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyCallWithNew); return {}; } Value ProxyConstructor::construct(Interpreter& interpreter, Function&) { if (interpreter.argument_count() < 2) { - interpreter.throw_exception(ErrorType::ProxyTwoArguments); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyTwoArguments); return {}; } @@ -66,11 +66,11 @@ Value ProxyConstructor::construct(Interpreter& interpreter, Function&) auto handler = interpreter.argument(1); if (!target.is_object()) { - interpreter.throw_exception(ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects().characters()); return {}; } if (!handler.is_object()) { - interpreter.throw_exception(ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects().characters()); return {}; } return ProxyObject::create(global_object(), target.as_object(), handler.as_object()); diff --git a/Libraries/LibJS/Runtime/ProxyObject.cpp b/Libraries/LibJS/Runtime/ProxyObject.cpp index 98318d1cb8e..f6b2e874fa3 100644 --- a/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -77,7 +77,7 @@ ProxyObject::~ProxyObject() Object* ProxyObject::prototype() { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return nullptr; } auto trap = m_handler.get("getPrototypeOf"); @@ -86,7 +86,7 @@ Object* ProxyObject::prototype() if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.prototype(); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "getPrototypeOf"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "getPrototypeOf"); return nullptr; } @@ -94,7 +94,7 @@ Object* ProxyObject::prototype() if (vm().exception()) return nullptr; if (!trap_result.is_object() && !trap_result.is_null()) { - interpreter().throw_exception(ErrorType::ProxyGetPrototypeOfReturn); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetPrototypeOfReturn); return nullptr; } if (m_target.is_extensible()) { @@ -108,7 +108,7 @@ Object* ProxyObject::prototype() if (vm().exception()) return nullptr; if (!same_value(interpreter(), trap_result, Value(target_proto))) { - interpreter().throw_exception(ErrorType::ProxyGetPrototypeOfNonExtensible); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetPrototypeOfNonExtensible); return nullptr; } return &trap_result.as_object(); @@ -117,7 +117,7 @@ Object* ProxyObject::prototype() const Object* ProxyObject::prototype() const { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return nullptr; } return const_cast(const_cast(this)->prototype()); @@ -126,7 +126,7 @@ const Object* ProxyObject::prototype() const bool ProxyObject::set_prototype(Object* object) { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("setPrototypeOf"); @@ -135,7 +135,7 @@ bool ProxyObject::set_prototype(Object* object) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.set_prototype(object); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "setPrototypeOf"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "setPrototypeOf"); return false; } @@ -148,7 +148,7 @@ bool ProxyObject::set_prototype(Object* object) if (vm().exception()) return false; if (!same_value(interpreter(), Value(object), Value(target_proto))) { - interpreter().throw_exception(ErrorType::ProxySetPrototypeOfNonExtensible); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxySetPrototypeOfNonExtensible); return false; } return true; @@ -157,7 +157,7 @@ bool ProxyObject::set_prototype(Object* object) bool ProxyObject::is_extensible() const { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("isExtensible"); @@ -166,7 +166,7 @@ bool ProxyObject::is_extensible() const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.is_extensible(); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "isExtensible"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "isExtensible"); return {}; } @@ -175,7 +175,7 @@ bool ProxyObject::is_extensible() const return false; if (trap_result != m_target.is_extensible()) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyIsExtensibleReturn); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyIsExtensibleReturn); return false; } return trap_result; @@ -184,7 +184,7 @@ bool ProxyObject::is_extensible() const bool ProxyObject::prevent_extensions() { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("preventExtensions"); @@ -193,7 +193,7 @@ bool ProxyObject::prevent_extensions() if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.prevent_extensions(); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "preventExtensions"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "preventExtensions"); return {}; } @@ -202,7 +202,7 @@ bool ProxyObject::prevent_extensions() return false; if (trap_result && m_target.is_extensible()) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyPreventExtensionsReturn); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyPreventExtensionsReturn); return false; } return trap_result; @@ -211,7 +211,7 @@ bool ProxyObject::prevent_extensions() Optional ProxyObject::get_own_property_descriptor(const PropertyName& name) const { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("getOwnPropertyDescriptor"); @@ -220,7 +220,7 @@ Optional ProxyObject::get_own_property_descriptor(const Prop if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.get_own_property_descriptor(name); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor"); return {}; } @@ -228,7 +228,7 @@ Optional ProxyObject::get_own_property_descriptor(const Prop if (vm().exception()) return {}; if (!trap_result.is_object() && !trap_result.is_undefined()) { - interpreter().throw_exception(ErrorType::ProxyGetOwnDescriptorReturn); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetOwnDescriptorReturn); return {}; } auto target_desc = m_target.get_own_property_descriptor(name); @@ -238,12 +238,12 @@ Optional ProxyObject::get_own_property_descriptor(const Prop if (!target_desc.has_value()) return {}; if (!target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception(ErrorType::ProxyGetOwnDescriptorNonConfigurable); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetOwnDescriptorNonConfigurable); return {}; } if (!m_target.is_extensible()) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyGetOwnDescriptorUndefReturn); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetOwnDescriptorUndefReturn); return {}; } return {}; @@ -253,11 +253,11 @@ Optional ProxyObject::get_own_property_descriptor(const Prop return {}; if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), result_desc, target_desc)) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyGetOwnDescriptorInvalidDescriptor); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidDescriptor); return {}; } if (!result_desc.attributes.is_configurable() && (!target_desc.has_value() || target_desc.value().attributes.is_configurable())) { - interpreter().throw_exception(ErrorType::ProxyGetOwnDescriptorInvalidNonConfig); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidNonConfig); return {}; } return result_desc; @@ -266,7 +266,7 @@ Optional ProxyObject::get_own_property_descriptor(const Prop bool ProxyObject::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions) { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("defineProperty"); @@ -275,7 +275,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.define_property(property_name, descriptor, throw_exceptions); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "defineProperty"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "defineProperty"); return false; } @@ -293,21 +293,21 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj if (!target_desc.has_value()) { if (!m_target.is_extensible()) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyDefinePropNonExtensible); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyDefinePropNonExtensible); return false; } if (setting_config_false) { - interpreter().throw_exception(ErrorType::ProxyDefinePropNonConfigurableNonExisting); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyDefinePropNonConfigurableNonExisting); return false; } } else { if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), PropertyDescriptor::from_dictionary(vm(), descriptor), target_desc)) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyDefinePropIncompatibleDescriptor); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyDefinePropIncompatibleDescriptor); return false; } if (setting_config_false && target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception(ErrorType::ProxyDefinePropExistingConfigurable); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyDefinePropExistingConfigurable); return false; } } @@ -317,7 +317,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj bool ProxyObject::has_property(const PropertyName& name) const { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("has"); @@ -326,7 +326,7 @@ bool ProxyObject::has_property(const PropertyName& name) const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.has_property(name); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "has"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "has"); return false; } @@ -339,12 +339,12 @@ bool ProxyObject::has_property(const PropertyName& name) const return false; if (target_desc.has_value()) { if (!target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception(ErrorType::ProxyHasExistingNonConfigurable); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyHasExistingNonConfigurable); return false; } if (!m_target.is_extensible()) { if (!vm().exception()) - interpreter().throw_exception(ErrorType::ProxyHasExistingNonExtensible); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyHasExistingNonExtensible); return false; } } @@ -355,7 +355,7 @@ bool ProxyObject::has_property(const PropertyName& name) const Value ProxyObject::get(const PropertyName& name, Value) const { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("get"); @@ -364,7 +364,7 @@ Value ProxyObject::get(const PropertyName& name, Value) const if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.get(name); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "get"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "get"); return {}; } @@ -376,11 +376,11 @@ Value ProxyObject::get(const PropertyName& name, Value) const if (vm().exception()) return {}; if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), trap_result, target_desc.value().value)) { - interpreter().throw_exception(ErrorType::ProxyGetImmutableDataProperty); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetImmutableDataProperty); return {}; } if (target_desc.value().is_accessor_descriptor() && target_desc.value().getter == nullptr && !trap_result.is_undefined()) { - interpreter().throw_exception(ErrorType::ProxyGetNonConfigurableAccessor); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyGetNonConfigurableAccessor); return {}; } } @@ -390,7 +390,7 @@ Value ProxyObject::get(const PropertyName& name, Value) const bool ProxyObject::put(const PropertyName& name, Value value, Value) { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return false; } auto trap = m_handler.get("set"); @@ -399,7 +399,7 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.put(name, value); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "set"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "set"); return false; } auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()), value, Value(const_cast(this))).to_boolean(); @@ -410,11 +410,11 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value) return false; if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) { if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), value, target_desc.value().value)) { - interpreter().throw_exception(ErrorType::ProxySetImmutableDataProperty); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxySetImmutableDataProperty); return false; } if (target_desc.value().is_accessor_descriptor() && !target_desc.value().setter) { - interpreter().throw_exception(ErrorType::ProxySetNonConfigurableAccessor); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxySetNonConfigurableAccessor); } } return true; @@ -423,7 +423,7 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value) Value ProxyObject::delete_property(const PropertyName& name) { if (m_is_revoked) { - interpreter().throw_exception(ErrorType::ProxyRevoked); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("deleteProperty"); @@ -432,7 +432,7 @@ Value ProxyObject::delete_property(const PropertyName& name) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return m_target.delete_property(name); if (!trap.is_function()) { - interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "deleteProperty"); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty"); return {}; } @@ -447,7 +447,7 @@ Value ProxyObject::delete_property(const PropertyName& name) if (!target_desc.has_value()) return Value(true); if (!target_desc.value().attributes.is_configurable()) { - interpreter().throw_exception(ErrorType::ProxyDeleteNonConfigurable); + interpreter().vm().throw_exception(global_object(), ErrorType::ProxyDeleteNonConfigurable); return {}; } return Value(true); @@ -463,11 +463,11 @@ void ProxyObject::visit_children(Cell::Visitor& visitor) Value ProxyObject::call(Interpreter& interpreter) { if (!is_function()) { - interpreter.throw_exception(ErrorType::NotAFunction, Value(this).to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAFunction, Value(this).to_string_without_side_effects().characters()); return {}; } if (m_is_revoked) { - interpreter.throw_exception(ErrorType::ProxyRevoked); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("apply"); @@ -476,7 +476,7 @@ Value ProxyObject::call(Interpreter& interpreter) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return static_cast(m_target).call(interpreter); if (!trap.is_function()) { - interpreter.throw_exception(ErrorType::ProxyInvalidTrap, "apply"); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "apply"); return {}; } MarkedValueList arguments(interpreter.heap()); @@ -484,7 +484,7 @@ Value ProxyObject::call(Interpreter& interpreter) arguments.append(Value(&m_handler)); // FIXME: Pass global object auto arguments_array = Array::create(interpreter.global_object()); - interpreter.for_each_argument([&](auto& argument) { + interpreter.vm().for_each_argument([&](auto& argument) { arguments_array->indexed_properties().append(argument); }); arguments.append(arguments_array); @@ -495,11 +495,11 @@ Value ProxyObject::call(Interpreter& interpreter) Value ProxyObject::construct(Interpreter& interpreter, Function& new_target) { if (!is_function()) { - interpreter.throw_exception(ErrorType::NotAConstructor, Value(this).to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAConstructor, Value(this).to_string_without_side_effects().characters()); return {}; } if (m_is_revoked) { - interpreter.throw_exception(ErrorType::ProxyRevoked); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyRevoked); return {}; } auto trap = m_handler.get("construct"); @@ -508,21 +508,21 @@ Value ProxyObject::construct(Interpreter& interpreter, Function& new_target) if (trap.is_empty() || trap.is_undefined() || trap.is_null()) return static_cast(m_target).construct(interpreter, new_target); if (!trap.is_function()) { - interpreter.throw_exception(ErrorType::ProxyInvalidTrap, "construct"); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyInvalidTrap, "construct"); return {}; } MarkedValueList arguments(interpreter.heap()); arguments.append(Value(&m_target)); auto arguments_array = Array::create(interpreter.global_object()); - interpreter.for_each_argument([&](auto& argument) { + interpreter.vm().for_each_argument([&](auto& argument) { arguments_array->indexed_properties().append(argument); }); arguments.append(arguments_array); arguments.append(Value(&new_target)); auto result = interpreter.call(trap.as_function(), Value(&m_handler), move(arguments)); if (!result.is_object()) { - interpreter.throw_exception(ErrorType::ProxyConstructBadReturnType); + interpreter.vm().throw_exception(global_object(), ErrorType::ProxyConstructBadReturnType); return {}; } return result; diff --git a/Libraries/LibJS/Runtime/Reference.cpp b/Libraries/LibJS/Runtime/Reference.cpp index e670a023703..1d21b4a380b 100644 --- a/Libraries/LibJS/Runtime/Reference.cpp +++ b/Libraries/LibJS/Runtime/Reference.cpp @@ -44,14 +44,14 @@ void Reference::put(Interpreter& interpreter, GlobalObject& global_object, Value if (is_local_variable() || is_global_variable()) { if (is_local_variable()) - interpreter.set_variable(m_name.to_string(), value, global_object); + interpreter.vm().set_variable(m_name.to_string(), value, global_object); else global_object.put(m_name, value); return; } if (!base().is_object() && interpreter.in_strict_mode()) { - interpreter.throw_exception(ErrorType::ReferencePrimitiveAssignment, m_name.to_string().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::ReferencePrimitiveAssignment, m_name.to_string().characters()); return; } @@ -62,14 +62,14 @@ void Reference::put(Interpreter& interpreter, GlobalObject& global_object, Value object->put(m_name, value); } -void Reference::throw_reference_error(Interpreter& interpreter, GlobalObject&) +void Reference::throw_reference_error(Interpreter& interpreter, GlobalObject& global_object) { auto property_name = m_name.to_string(); String message; if (property_name.is_empty()) { - interpreter.throw_exception(ErrorType::ReferenceUnresolvable); + interpreter.vm().throw_exception(global_object, ErrorType::ReferenceUnresolvable); } else { - interpreter.throw_exception(ErrorType::UnknownIdentifier, property_name.characters()); + interpreter.vm().throw_exception(global_object, ErrorType::UnknownIdentifier, property_name.characters()); } } @@ -85,7 +85,7 @@ Value Reference::get(Interpreter& interpreter, GlobalObject& global_object) if (is_local_variable() || is_global_variable()) { Value value; if (is_local_variable()) - value = interpreter.get_variable(m_name.to_string(), global_object); + value = interpreter.vm().get_variable(m_name.to_string(), global_object); else value = global_object.get(m_name); if (interpreter.exception()) diff --git a/Libraries/LibJS/Runtime/ReflectObject.cpp b/Libraries/LibJS/Runtime/ReflectObject.cpp index ec667690a8d..4c08a8d7ec0 100644 --- a/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -38,7 +38,7 @@ static Object* get_target_object_from(Interpreter& interpreter, const String& na { auto target = interpreter.argument(0); if (!target.is_object()) { - interpreter.throw_exception(ErrorType::ReflectArgumentMustBeAnObject, name.characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::ReflectArgumentMustBeAnObject, name.characters()); return nullptr; } return static_cast(&target.as_object()); @@ -48,7 +48,7 @@ static Function* get_target_function_from(Interpreter& interpreter, const String { auto target = interpreter.argument(0); if (!target.is_function()) { - interpreter.throw_exception(ErrorType::ReflectArgumentMustBeAFunction, name.characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::ReflectArgumentMustBeAFunction, name.characters()); return nullptr; } return &target.as_function(); @@ -57,7 +57,7 @@ static Function* get_target_function_from(Interpreter& interpreter, const String static void prepare_arguments_list(Interpreter& interpreter, Value value, MarkedValueList* arguments) { if (!value.is_object()) { - interpreter.throw_exception(ErrorType::ReflectBadArgumentsList); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::ReflectBadArgumentsList); return; } auto& arguments_list = value.as_object(); @@ -130,12 +130,12 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::construct) auto new_target_value = interpreter.argument(2); if (!new_target_value.is_function() || (new_target_value.as_object().is_native_function() && !static_cast(new_target_value.as_object()).has_constructor())) { - interpreter.throw_exception(ErrorType::ReflectBadNewTarget); + interpreter.vm().throw_exception(global_object, ErrorType::ReflectBadNewTarget); return {}; } new_target = &new_target_value.as_function(); } - return interpreter.construct(*target, *new_target, move(arguments), global_object); + return interpreter.vm().construct(*target, *new_target, move(arguments), global_object); } JS_DEFINE_NATIVE_FUNCTION(ReflectObject::define_property) @@ -144,7 +144,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::define_property) if (!target) return {}; if (!interpreter.argument(2).is_object()) { - interpreter.throw_exception(ErrorType::ReflectBadDescriptorArgument); + interpreter.vm().throw_exception(global_object, ErrorType::ReflectBadDescriptorArgument); return {}; } auto property_key = StringOrSymbol::from_value(interpreter, interpreter.argument(1)); @@ -268,7 +268,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::set_prototype_of) return {}; auto prototype_value = interpreter.argument(1); if (!prototype_value.is_object() && !prototype_value.is_null()) { - interpreter.throw_exception(ErrorType::ObjectPrototypeWrongType); + interpreter.vm().throw_exception(global_object, ErrorType::ObjectPrototypeWrongType); return {}; } Object* prototype = nullptr; diff --git a/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Libraries/LibJS/Runtime/ScriptFunction.cpp index 8f670f1bc6e..ed03190b4f4 100644 --- a/Libraries/LibJS/Runtime/ScriptFunction.cpp +++ b/Libraries/LibJS/Runtime/ScriptFunction.cpp @@ -41,7 +41,7 @@ static ScriptFunction* typed_this(Interpreter& interpreter, GlobalObject& global if (!this_object) return nullptr; if (!this_object->is_function()) { - interpreter.throw_exception(ErrorType::NotAFunctionNoParam); + interpreter.vm().throw_exception(global_object, ErrorType::NotAFunctionNoParam); return nullptr; } return static_cast(this_object); @@ -130,13 +130,13 @@ Value ScriptFunction::call(Interpreter& interpreter) arguments.append({ parameter.name, value }); interpreter.current_environment()->set(parameter.name, { value, DeclarationKind::Var }); } - return interpreter.execute_statement(global_object(), m_body, arguments, ScopeType::Function); + return interpreter.vm().execute_statement(global_object(), m_body, arguments, ScopeType::Function); } Value ScriptFunction::construct(Interpreter& interpreter, Function&) { if (m_is_arrow_function) { - interpreter.throw_exception(ErrorType::NotAConstructor, m_name.characters()); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAConstructor, m_name.characters()); return {}; } return call(interpreter); diff --git a/Libraries/LibJS/Runtime/StringConstructor.cpp b/Libraries/LibJS/Runtime/StringConstructor.cpp index 1edc7a141fa..1e7f7404bb4 100644 --- a/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -89,7 +89,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw) if (interpreter.exception()) return {}; if (raw.is_empty() || raw.is_undefined() || raw.is_null()) { - interpreter.throw_exception(ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined"); + interpreter.vm().throw_exception(global_object, ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined"); return {}; } if (!raw.is_array()) diff --git a/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp b/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp index 05f10c88dfa..29d3d2fd1a9 100644 --- a/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp @@ -54,7 +54,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringIteratorPrototype::next) { auto this_value = interpreter.this_value(global_object); if (!this_value.is_object() || !this_value.as_object().is_string_iterator_object()) { - interpreter.throw_exception(ErrorType::NotA, "String Iterator"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "String Iterator"); return {}; } diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp index 10a2e2ff717..441a82f4249 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -46,7 +46,7 @@ static StringObject* typed_this(Interpreter& interpreter, GlobalObject& global_o if (!this_object) return nullptr; if (!this_object->is_string_object()) { - interpreter.throw_exception(ErrorType::NotA, "String"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "String"); return nullptr; } return static_cast(this_object); @@ -141,11 +141,11 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::repeat) if (interpreter.exception()) return {}; if (count_value.as_double() < 0) { - interpreter.throw_exception(ErrorType::StringRepeatCountMustBe, "positive"); + interpreter.vm().throw_exception(global_object, ErrorType::StringRepeatCountMustBe, "positive"); return {}; } if (count_value.is_infinity()) { - interpreter.throw_exception(ErrorType::StringRepeatCountMustBe, "finite"); + interpreter.vm().throw_exception(global_object, ErrorType::StringRepeatCountMustBe, "finite"); return {}; } auto count = count_value.to_size_t(interpreter); @@ -460,7 +460,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::symbol_iterator) { auto this_object = interpreter.this_value(global_object); if (this_object.is_undefined() || this_object.is_null()) { - interpreter.throw_exception(ErrorType::ToObjectNullOrUndef); + interpreter.vm().throw_exception(global_object, ErrorType::ToObjectNullOrUndef); return {}; } diff --git a/Libraries/LibJS/Runtime/SymbolConstructor.cpp b/Libraries/LibJS/Runtime/SymbolConstructor.cpp index 47ff1283b24..64de9db9ffb 100644 --- a/Libraries/LibJS/Runtime/SymbolConstructor.cpp +++ b/Libraries/LibJS/Runtime/SymbolConstructor.cpp @@ -65,7 +65,7 @@ Value SymbolConstructor::call(Interpreter& interpreter) Value SymbolConstructor::construct(Interpreter& interpreter, Function&) { - interpreter.throw_exception(ErrorType::NotAConstructor, "Symbol"); + interpreter.vm().throw_exception(global_object(), ErrorType::NotAConstructor, "Symbol"); return {}; } @@ -85,7 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::key_for) { auto argument = interpreter.argument(0); if (!argument.is_symbol()) { - interpreter.throw_exception(ErrorType::NotASymbol, argument.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(global_object, ErrorType::NotASymbol, argument.to_string_without_side_effects().characters()); return {}; } diff --git a/Libraries/LibJS/Runtime/SymbolPrototype.cpp b/Libraries/LibJS/Runtime/SymbolPrototype.cpp index 78cfff84e17..b13faa7c781 100644 --- a/Libraries/LibJS/Runtime/SymbolPrototype.cpp +++ b/Libraries/LibJS/Runtime/SymbolPrototype.cpp @@ -64,7 +64,7 @@ static SymbolObject* typed_this(Interpreter& interpreter, GlobalObject& global_o if (!this_object) return nullptr; if (!this_object->is_symbol_object()) { - interpreter.throw_exception(ErrorType::NotA, "Symbol"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Symbol"); return nullptr; } return static_cast(this_object); diff --git a/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp b/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp index e6163f5923e..d16bed089f5 100644 --- a/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp +++ b/Libraries/LibJS/Runtime/Uint8ClampedArray.cpp @@ -59,7 +59,7 @@ JS_DEFINE_NATIVE_GETTER(Uint8ClampedArray::length_getter) if (!this_object) return {}; if (StringView(this_object->class_name()) != "Uint8ClampedArray") { - interpreter.throw_exception(ErrorType::NotA, "Uint8ClampedArray"); + interpreter.vm().throw_exception(global_object, ErrorType::NotA, "Uint8ClampedArray"); return {}; } return Value(static_cast(this_object)->length()); diff --git a/Libraries/LibJS/Runtime/VM.cpp b/Libraries/LibJS/Runtime/VM.cpp index 37c73418723..9989ca9172c 100644 --- a/Libraries/LibJS/Runtime/VM.cpp +++ b/Libraries/LibJS/Runtime/VM.cpp @@ -24,10 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include +#include +#include +#include +#include #include #include +//#define VM_DEBUG + namespace JS { NonnullRefPtr VM::create() @@ -90,8 +98,19 @@ void VM::gather_roots(HashTable& roots) roots.set(m_empty_string); if (m_exception) roots.set(m_exception); - for (auto* interpreter : m_interpreters) - interpreter->gather_roots(roots); + + if (m_last_value.is_cell()) + roots.set(m_last_value.as_cell()); + + for (auto& call_frame : m_call_stack) { + if (call_frame.this_value.is_cell()) + roots.set(call_frame.this_value.as_cell()); + for (auto& argument : call_frame.arguments) { + if (argument.is_cell()) + roots.set(argument.as_cell()); + } + roots.set(call_frame.environment); + } #define __JS_ENUMERATE(SymbolName, snake_name) \ roots.set(well_known_symbol_##snake_name()); @@ -113,4 +132,266 @@ Symbol* VM::get_global_symbol(const String& description) return new_global_symbol; } +bool VM::in_strict_mode() const +{ + if (m_scope_stack.is_empty()) + return true; + return m_scope_stack.last().scope_node->in_strict_mode(); +} + +void VM::enter_scope(const ScopeNode& scope_node, ArgumentVector arguments, ScopeType scope_type, GlobalObject& global_object) +{ + for (auto& declaration : scope_node.functions()) { + auto* function = ScriptFunction::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), current_environment()); + set_variable(declaration.name(), function, global_object); + } + + if (scope_type == ScopeType::Function) { + m_scope_stack.append({ scope_type, scope_node, false }); + return; + } + + HashMap scope_variables_with_declaration_kind; + scope_variables_with_declaration_kind.ensure_capacity(16); + + for (auto& declaration : scope_node.variables()) { + for (auto& declarator : declaration.declarations()) { + if (scope_node.is_program()) { + global_object.put(declarator.id().string(), js_undefined()); + if (exception()) + return; + } else { + scope_variables_with_declaration_kind.set(declarator.id().string(), { js_undefined(), declaration.declaration_kind() }); + } + } + } + + for (auto& argument : arguments) { + scope_variables_with_declaration_kind.set(argument.name, { argument.value, DeclarationKind::Var }); + } + + bool pushed_lexical_environment = false; + + if (!scope_variables_with_declaration_kind.is_empty()) { + auto* block_lexical_environment = heap().allocate(global_object, move(scope_variables_with_declaration_kind), current_environment()); + m_call_stack.last().environment = block_lexical_environment; + pushed_lexical_environment = true; + } + + m_scope_stack.append({ scope_type, scope_node, pushed_lexical_environment }); +} + +void VM::exit_scope(const ScopeNode& scope_node) +{ + while (!m_scope_stack.is_empty()) { + auto popped_scope = m_scope_stack.take_last(); + if (popped_scope.pushed_environment) + m_call_stack.last().environment = m_call_stack.last().environment->parent(); + if (popped_scope.scope_node.ptr() == &scope_node) + break; + } + + // If we unwind all the way, just reset m_unwind_until so that future "return" doesn't break. + if (m_scope_stack.is_empty()) + m_unwind_until = ScopeType::None; +} + +void VM::set_variable(const FlyString& name, Value value, GlobalObject& global_object, bool first_assignment) +{ + if (m_call_stack.size()) { + for (auto* environment = current_environment(); environment; environment = environment->parent()) { + if (environment->type() == LexicalEnvironment::EnvironmentRecordType::Global) + break; + auto possible_match = environment->get(name); + if (possible_match.has_value()) { + if (!first_assignment && possible_match.value().declaration_kind == DeclarationKind::Const) { + throw_exception(global_object, ErrorType::InvalidAssignToConst); + return; + } + + environment->set(name, { value, possible_match.value().declaration_kind }); + return; + } + } + } + + global_object.put(move(name), move(value)); +} + +Value VM::get_variable(const FlyString& name, GlobalObject& global_object) +{ + if (m_call_stack.size()) { + for (auto* environment = current_environment(); environment; environment = environment->parent()) { + if (environment->type() == LexicalEnvironment::EnvironmentRecordType::Global) + break; + auto possible_match = environment->get(name); + if (possible_match.has_value()) + return possible_match.value().value; + } + } + auto value = global_object.get(name); + if (m_underscore_is_last_value && name == "_" && value.is_empty()) + return m_last_value; + return value; +} + +Reference VM::get_reference(const FlyString& name) +{ + if (m_call_stack.size()) { + for (auto* environment = current_environment(); environment; environment = environment->parent()) { + if (environment->type() == LexicalEnvironment::EnvironmentRecordType::Global) + break; + auto possible_match = environment->get(name); + if (possible_match.has_value()) + return { Reference::LocalVariable, name }; + } + } + return { Reference::GlobalVariable, name }; +} + +Value VM::execute_statement(GlobalObject& global_object, const Statement& statement, ArgumentVector arguments, ScopeType scope_type) +{ + if (!statement.is_scope_node()) + return statement.execute(interpreter(), global_object); + + auto& block = static_cast(statement); + enter_scope(block, move(arguments), scope_type, global_object); + + if (block.children().is_empty()) + m_last_value = js_undefined(); + + for (auto& node : block.children()) { + m_last_value = node.execute(interpreter(), global_object); + if (should_unwind()) { + if (!block.label().is_null() && should_unwind_until(ScopeType::Breakable, block.label())) + stop_unwind(); + break; + } + } + + bool did_return = m_unwind_until == ScopeType::Function; + + if (m_unwind_until == scope_type) + m_unwind_until = ScopeType::None; + + exit_scope(block); + + return did_return ? m_last_value : js_undefined(); +} + +Value VM::construct(Function& function, Function& new_target, Optional arguments, GlobalObject& global_object) +{ + auto& call_frame = push_call_frame(); + + ArmedScopeGuard call_frame_popper = [&] { + pop_call_frame(); + }; + + call_frame.function_name = function.name(); + call_frame.arguments = function.bound_arguments(); + if (arguments.has_value()) + call_frame.arguments.append(arguments.value().values()); + call_frame.environment = function.create_environment(); + + current_environment()->set_new_target(&new_target); + + Object* new_object = nullptr; + if (function.constructor_kind() == Function::ConstructorKind::Base) { + new_object = Object::create_empty(global_object); + current_environment()->bind_this_value(new_object); + if (exception()) + return {}; + auto prototype = new_target.get("prototype"); + if (exception()) + return {}; + if (prototype.is_object()) { + new_object->set_prototype(&prototype.as_object()); + if (exception()) + return {}; + } + } + + // If we are a Derived constructor, |this| has not been constructed before super is called. + Value this_value = function.constructor_kind() == Function::ConstructorKind::Base ? new_object : Value {}; + call_frame.this_value = this_value; + auto result = function.construct(interpreter(), new_target); + + this_value = current_environment()->get_this_binding(); + pop_call_frame(); + call_frame_popper.disarm(); + + // If we are constructing an instance of a derived class, + // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses). + if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) { + current_environment()->replace_this_binding(result); + auto prototype = new_target.get("prototype"); + if (exception()) + return {}; + if (prototype.is_object()) { + result.as_object().set_prototype(&prototype.as_object()); + if (exception()) + return {}; + } + return result; + } + + if (exception()) + return {}; + + if (result.is_object()) + return result; + + return this_value; +} + +void VM::throw_exception(Exception* exception) +{ +#ifdef VM_DEBUG + if (exception->value().is_object() && exception->value().as_object().is_error()) { + auto& error = static_cast(exception->value().as_object()); + dbg() << "Throwing JavaScript Error: " << error.name() << ", " << error.message(); + + for (ssize_t i = m_call_stack.size() - 1; i >= 0; --i) { + auto function_name = m_call_stack[i].function_name; + if (function_name.is_empty()) + function_name = ""; + dbg() << " " << function_name; + } + } +#endif + m_exception = exception; + unwind(ScopeType::Try); +} + +String VM::join_arguments() const +{ + StringBuilder joined_arguments; + for (size_t i = 0; i < argument_count(); ++i) { + joined_arguments.append(argument(i).to_string_without_side_effects().characters()); + if (i != argument_count() - 1) + joined_arguments.append(' '); + } + return joined_arguments.build(); +} + +Value VM::resolve_this_binding() const +{ + return get_this_environment()->get_this_binding(); +} + +const LexicalEnvironment* VM::get_this_environment() const +{ + // We will always return because the Global environment will always be reached, which has a |this| binding. + for (const LexicalEnvironment* environment = current_environment(); environment; environment = environment->parent()) { + if (environment->has_this_binding()) + return environment; + } + ASSERT_NOT_REACHED(); +} + +Value VM::get_new_target() const +{ + return get_this_environment()->new_target(); +} + } diff --git a/Libraries/LibJS/Runtime/VM.h b/Libraries/LibJS/Runtime/VM.h index b0996434727..07e522140a5 100644 --- a/Libraries/LibJS/Runtime/VM.h +++ b/Libraries/LibJS/Runtime/VM.h @@ -26,12 +26,45 @@ #pragma once +#include #include #include #include +#include +#include +#include namespace JS { +enum class ScopeType { + None, + Function, + Block, + Try, + Breakable, + Continuable, +}; + +struct ScopeFrame { + ScopeType type; + NonnullRefPtr scope_node; + bool pushed_environment { false }; +}; + +struct CallFrame { + FlyString function_name; + Value this_value; + Vector arguments; + LexicalEnvironment* environment { nullptr }; +}; + +struct Argument { + FlyString name; + Value value; +}; + +typedef Vector ArgumentVector; + class VM : public RefCounted { public: static NonnullRefPtr create(); @@ -50,7 +83,7 @@ public: { return m_exception; } - void set_exception(Badge, Exception* exception) { m_exception = exception; } + void clear_exception() { m_exception = nullptr; } class InterpreterExecutionScope { @@ -73,6 +106,107 @@ public: PrimitiveString& empty_string() { return *m_empty_string; } + CallFrame& push_call_frame() + { + m_call_stack.append({ {}, js_undefined(), {}, nullptr }); + return m_call_stack.last(); + } + void pop_call_frame() { m_call_stack.take_last(); } + const CallFrame& call_frame() { return m_call_stack.last(); } + const Vector& call_stack() const { return m_call_stack; } + Vector& call_stack() { return m_call_stack; } + + const LexicalEnvironment* current_environment() const { return m_call_stack.last().environment; } + LexicalEnvironment* current_environment() { return m_call_stack.last().environment; } + + bool in_strict_mode() const; + + template + void for_each_argument(Callback callback) + { + if (m_call_stack.is_empty()) + return; + for (auto& value : m_call_stack.last().arguments) + callback(value); + } + + size_t argument_count() const + { + if (m_call_stack.is_empty()) + return 0; + return m_call_stack.last().arguments.size(); + } + + Value argument(size_t index) const + { + if (m_call_stack.is_empty()) + return {}; + auto& arguments = m_call_stack.last().arguments; + return index < arguments.size() ? arguments[index] : js_undefined(); + } + + Value this_value(Object& global_object) const + { + if (m_call_stack.is_empty()) + return &global_object; + return m_call_stack.last().this_value; + } + + Value last_value() const { return m_last_value; } + + bool underscore_is_last_value() const { return m_underscore_is_last_value; } + void set_underscore_is_last_value(bool b) { m_underscore_is_last_value = b; } + + void unwind(ScopeType type, FlyString label = {}) + { + m_unwind_until = type; + m_unwind_until_label = label; + } + void stop_unwind() { m_unwind_until = ScopeType::None; } + bool should_unwind_until(ScopeType type, FlyString label) const + { + if (m_unwind_until_label.is_null()) + return m_unwind_until == type; + return m_unwind_until == type && m_unwind_until_label == label; + } + bool should_unwind() const { return m_unwind_until != ScopeType::None; } + + Value get_variable(const FlyString& name, GlobalObject&); + void set_variable(const FlyString& name, Value, GlobalObject&, bool first_assignment = false); + + Reference get_reference(const FlyString& name); + + void enter_scope(const ScopeNode&, ArgumentVector, ScopeType, GlobalObject&); + void exit_scope(const ScopeNode&); + + template + void throw_exception(GlobalObject& global_object, Args&&... args) + { + return throw_exception(global_object, T::create(global_object, forward(args)...)); + } + + void throw_exception(Exception*); + void throw_exception(GlobalObject& global_object, Value value) + { + return throw_exception(heap().allocate(global_object, value)); + } + + template + void throw_exception(GlobalObject& global_object, ErrorType type, Args&&... args) + { + return throw_exception(global_object, T::create(global_object, String::format(type.message(), forward(args)...))); + } + + Value execute_statement(GlobalObject&, const Statement&, ArgumentVector = {}, ScopeType = ScopeType::Block); + + Value construct(Function&, Function& new_target, Optional arguments, GlobalObject&); + + String join_arguments() const; + + Value resolve_this_binding() const; + const LexicalEnvironment* get_this_environment() const; + Value get_new_target() const; + private: VM(); @@ -81,6 +215,15 @@ private: Heap m_heap; Vector m_interpreters; + Vector m_scope_stack; + Vector m_call_stack; + + Value m_last_value; + ScopeType m_unwind_until { ScopeType::None }; + FlyString m_unwind_until_label; + + bool m_underscore_is_last_value { false }; + HashMap m_global_symbol_map; PrimitiveString* m_empty_string { nullptr }; diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index e637362a20d..0b39b08a44e 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -163,7 +163,7 @@ String Value::to_string(Interpreter& interpreter) const case Type::String: return m_value.as_string->string(); case Type::Symbol: - interpreter.throw_exception(ErrorType::Convert, "symbol", "string"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "symbol", "string"); return {}; case Type::BigInt: return m_value.as_bigint->big_integer().to_base10(); @@ -215,7 +215,7 @@ Object* Value::to_object(Interpreter& interpreter, GlobalObject& global_object) switch (m_type) { case Type::Undefined: case Type::Null: - interpreter.throw_exception(ErrorType::ToObjectNullOrUndef); + interpreter.vm().throw_exception(global_object, ErrorType::ToObjectNullOrUndef); return nullptr; case Type::Boolean: return BooleanObject::create(global_object, m_value.as_bool); @@ -271,10 +271,10 @@ Value Value::to_number(Interpreter& interpreter) const return Value(parsed_double); } case Type::Symbol: - interpreter.throw_exception(ErrorType::Convert, "symbol", "number"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "symbol", "number"); return {}; case Type::BigInt: - interpreter.throw_exception(ErrorType::Convert, "BigInt", "number"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "BigInt", "number"); return {}; case Type::Object: { auto primitive = m_value.as_object->to_primitive(PreferredType::Number); @@ -294,10 +294,10 @@ BigInt* Value::to_bigint(Interpreter& interpreter) const return nullptr; switch (primitive.type()) { case Type::Undefined: - interpreter.throw_exception(ErrorType::Convert, "undefined", "BigInt"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "undefined", "BigInt"); return nullptr; case Type::Null: - interpreter.throw_exception(ErrorType::Convert, "null", "BigInt"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "null", "BigInt"); return nullptr; case Type::Boolean: { auto value = primitive.as_bool() ? 1 : 0; @@ -306,18 +306,18 @@ BigInt* Value::to_bigint(Interpreter& interpreter) const case Type::BigInt: return &primitive.as_bigint(); case Type::Number: - interpreter.throw_exception(ErrorType::Convert, "number", "BigInt"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "number", "BigInt"); return {}; case Type::String: { auto& string = primitive.as_string().string(); if (!is_valid_bigint_value(string)) { - interpreter.throw_exception(ErrorType::BigIntInvalidValue, string.characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntInvalidValue, string.characters()); return {}; } return js_bigint(interpreter, Crypto::SignedBigInteger::from_base10(string.trim_whitespace())); } case Type::Symbol: - interpreter.throw_exception(ErrorType::Convert, "symbol", "BigInt"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::Convert, "symbol", "BigInt"); return {}; default: ASSERT_NOT_REACHED(); @@ -416,7 +416,7 @@ Value bitwise_and(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); return {}; } @@ -439,7 +439,7 @@ Value bitwise_or(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); return {}; } @@ -462,7 +462,7 @@ Value bitwise_xor(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); return {}; } @@ -518,7 +518,7 @@ Value left_shift(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) TODO(); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "left-shift"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "left-shift"); return {}; } @@ -539,7 +539,7 @@ Value right_shift(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) TODO(); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "right-shift"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "right-shift"); return {}; } @@ -558,7 +558,7 @@ Value unsigned_right_shift(Interpreter& interpreter, Value lhs, Value rhs) return lhs_numeric; return Value((unsigned)lhs_numeric.as_double() >> (i32)rhs_numeric.as_double()); } - interpreter.throw_exception(ErrorType::BigIntBadOperator, "unsigned right-shift"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperator, "unsigned right-shift"); return {}; } @@ -594,7 +594,7 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() + rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "addition"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "addition"); return {}; } @@ -610,7 +610,7 @@ Value sub(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() - rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "subtraction"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "subtraction"); return {}; } @@ -626,7 +626,7 @@ Value mul(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() * rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "multiplication"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "multiplication"); return {}; } @@ -642,7 +642,7 @@ Value div(Interpreter& interpreter, Value lhs, Value rhs) return Value(lhs_numeric.as_double() / rhs_numeric.as_double()); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "division"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "division"); return {}; } @@ -664,7 +664,7 @@ Value mod(Interpreter& interpreter, Value lhs, Value rhs) } if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "modulo"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "modulo"); return {}; } @@ -680,14 +680,14 @@ Value exp(Interpreter& interpreter, Value lhs, Value rhs) return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double())); if (both_bigint(lhs_numeric, rhs_numeric)) return js_bigint(interpreter, Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer())); - interpreter.throw_exception(ErrorType::BigIntBadOperatorOtherType, "exponentiation"); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "exponentiation"); return {}; } Value in(Interpreter& interpreter, Value lhs, Value rhs) { if (!rhs.is_object()) { - interpreter.throw_exception(ErrorType::InOperatorWithObject); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::InOperatorWithObject); return {}; } auto lhs_string = lhs.to_string(interpreter); @@ -699,13 +699,13 @@ Value in(Interpreter& interpreter, Value lhs, Value rhs) Value instance_of(Interpreter& interpreter, Value lhs, Value rhs) { if (!rhs.is_object()) { - interpreter.throw_exception(ErrorType::NotAnObject, rhs.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::NotAnObject, rhs.to_string_without_side_effects().characters()); return {}; } auto has_instance_method = rhs.as_object().get(interpreter.vm().well_known_symbol_has_instance()); if (!has_instance_method.is_empty()) { if (!has_instance_method.is_function()) { - interpreter.throw_exception(ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters()); return {}; } @@ -713,7 +713,7 @@ Value instance_of(Interpreter& interpreter, Value lhs, Value rhs) } if (!rhs.is_function()) { - interpreter.throw_exception(ErrorType::NotAFunction, rhs.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::NotAFunction, rhs.to_string_without_side_effects().characters()); return {}; } return ordinary_has_instance(interpreter, lhs, rhs); @@ -739,7 +739,7 @@ Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs) return {}; if (!rhs_prototype.is_object()) { - interpreter.throw_exception(ErrorType::InstanceOfOperatorBadPrototype, rhs_prototype.to_string_without_side_effects().characters()); + interpreter.vm().throw_exception(interpreter.global_object(), ErrorType::InstanceOfOperatorBadPrototype, rhs_prototype.to_string_without_side_effects().characters()); return {}; } while (true) { diff --git a/Libraries/LibWeb/Bindings/WindowObject.cpp b/Libraries/LibWeb/Bindings/WindowObject.cpp index 7050b200b6b..25540e6293b 100644 --- a/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -107,7 +107,7 @@ static DOM::Window* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& gl return nullptr; } if (StringView("WindowObject") != this_object->class_name()) { - interpreter.throw_exception(JS::ErrorType::NotA, "WindowObject"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, "WindowObject"); return nullptr; } return &static_cast(this_object)->impl(); @@ -148,14 +148,14 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); return {}; } auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object); if (!callback_object) return {}; if (!callback_object->is_function()) { - interpreter.throw_exception(JS::ErrorType::NotAFunctionNoParam); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotAFunctionNoParam); return {}; } i32 interval = 0; @@ -177,14 +177,14 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountAtLeastOne, "setTimeout"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setTimeout"); return {}; } auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object); if (!callback_object) return {}; if (!callback_object->is_function()) { - interpreter.throw_exception(JS::ErrorType::NotAFunctionNoParam); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotAFunctionNoParam); return {}; } i32 interval = 0; @@ -206,7 +206,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout"); return {}; } i32 timer_id = interpreter.argument(0).to_i32(interpreter); @@ -222,7 +222,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountAtLeastOne, "clearInterval"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearInterval"); return {}; } i32 timer_id = interpreter.argument(0).to_i32(interpreter); @@ -238,14 +238,14 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); return {}; } auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object); if (!callback_object) return {}; if (!callback_object->is_function()) { - interpreter.throw_exception(JS::ErrorType::NotAFunctionNoParam); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotAFunctionNoParam); return {}; } return JS::Value(impl->request_animation_frame(*static_cast(callback_object))); @@ -257,7 +257,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); return {}; } auto id = interpreter.argument(0).to_i32(interpreter); @@ -273,7 +273,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountOne, "atob"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountOne, "atob"); return {}; } auto string = interpreter.argument(0).to_string(interpreter); @@ -291,7 +291,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa) if (!impl) return {}; if (!interpreter.argument_count()) { - interpreter.throw_exception(JS::ErrorType::BadArgCountOne, "btoa"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountOne, "btoa"); return {}; } auto string = interpreter.argument(0).to_string(interpreter); @@ -302,7 +302,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa) byte_string.ensure_capacity(string.length()); for (u32 code_point : Utf8View(string)) { if (code_point > 0xff) { - interpreter.throw_exception(JS::ErrorType::NotAByteString, "btoa"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotAByteString, "btoa"); return {}; } byte_string.append(code_point); diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp index 7d0d066da24..d9e3310e1ee 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp @@ -64,7 +64,7 @@ static XMLHttpRequest* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& if (!this_object) return nullptr; if (StringView("XMLHttpRequestWrapper") != this_object->class_name()) { - interpreter.throw_exception(JS::ErrorType::NotA, "XMLHttpRequest"); + interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, "XMLHttpRequest"); return nullptr; } return &static_cast(this_object)->impl(); diff --git a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index fa5e73d09d8..65cd7f38384 100644 --- a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -506,7 +506,7 @@ void generate_implementation(const IDL::Interface& interface) out() << " if (!this_object)"; out() << " return {};"; out() << " if (!this_object->inherits(\"" << wrapper_class << "\")) {"; - out() << " interpreter.throw_exception(JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");"; + out() << " interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");"; out() << " return nullptr;"; out() << " }"; out() << " return &static_cast<" << wrapper_class << "*>(this_object)->impl();"; @@ -526,7 +526,7 @@ void generate_implementation(const IDL::Interface& interface) generate_return(); } else if (parameter.type.name == "EventListener") { out() << " if (!" << js_name << js_suffix << ".is_function()) {"; - out() << " interpreter.throw_exception(JS::ErrorType::NotA, \"Function\");"; + out() << " interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, \"Function\");"; generate_return(); out() << " }"; out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));"; @@ -535,7 +535,7 @@ void generate_implementation(const IDL::Interface& interface) out() << " if (interpreter.exception())"; generate_return(); out() << " if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {"; - out() << " interpreter.throw_exception(JS::ErrorType::NotA, \"" << parameter.type.name << "\");"; + out() << " interpreter.vm().throw_exception(global_object, JS::ErrorType::NotA, \"" << parameter.type.name << "\");"; generate_return(); out() << " }"; out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();"; @@ -658,9 +658,9 @@ void generate_implementation(const IDL::Interface& interface) if (function.length() > 0) { out() << " if (interpreter.argument_count() < " << function.length() << ") {"; if (function.length() == 1) - out() << " interpreter.throw_exception(JS::ErrorType::BadArgCountOne, \"" << function.name << "\");"; + out() << " interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountOne, \"" << function.name << "\");"; else - out() << " interpreter.throw_exception(JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");"; + out() << " interpreter.vm().throw_exception(global_object, JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");"; out() << " return {};"; out() << " }"; } diff --git a/Userland/js.cpp b/Userland/js.cpp index 5a9dc05834e..24b0d05e1e2 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -349,7 +349,7 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source auto hint = error.source_location_hint(source); if (!hint.is_empty()) printf("%s\n", hint.characters()); - interpreter.throw_exception(error.to_string()); + vm->throw_exception(interpreter.global_object(), error.to_string()); } else { interpreter.run(interpreter.global_object(), *program); } @@ -362,11 +362,11 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source for (auto& function_name : trace) printf(" -> %s\n", function_name.characters()); } - interpreter.vm().clear_exception(); + vm->clear_exception(); return false; } if (s_print_last_result) - print(interpreter.last_value()); + print(vm->last_value()); return true; } @@ -470,32 +470,32 @@ public: virtual JS::Value log() override { - puts(interpreter().join_arguments().characters()); + puts(interpreter().vm().join_arguments().characters()); return JS::js_undefined(); } virtual JS::Value info() override { - printf("(i) %s\n", interpreter().join_arguments().characters()); + printf("(i) %s\n", interpreter().vm().join_arguments().characters()); return JS::js_undefined(); } virtual JS::Value debug() override { printf("\033[36;1m"); - puts(interpreter().join_arguments().characters()); + puts(interpreter().vm().join_arguments().characters()); printf("\033[0m"); return JS::js_undefined(); } virtual JS::Value warn() override { printf("\033[33;1m"); - puts(interpreter().join_arguments().characters()); + puts(interpreter().vm().join_arguments().characters()); printf("\033[0m"); return JS::js_undefined(); } virtual JS::Value error() override { printf("\033[31;1m"); - puts(interpreter().join_arguments().characters()); + puts(interpreter().vm().join_arguments().characters()); printf("\033[0m"); return JS::js_undefined(); } @@ -507,7 +507,7 @@ public: } virtual JS::Value trace() override { - puts(interpreter().join_arguments().characters()); + puts(interpreter().vm().join_arguments().characters()); auto trace = get_trace(); for (auto& function_name : trace) { if (function_name.is_empty()) @@ -558,7 +558,7 @@ int main(int argc, char** argv) interrupt_interpreter = [&] { auto error = JS::Error::create(interpreter->global_object(), "Error", "Received SIGINT"); - interpreter->throw_exception(error); + vm->throw_exception(interpreter->global_object(), error); }; if (script_path == nullptr) { @@ -567,7 +567,7 @@ int main(int argc, char** argv) ReplConsoleClient console_client(interpreter->console()); interpreter->console().set_client(console_client); interpreter->heap().set_should_collect_on_every_allocation(gc_on_every_allocation); - interpreter->set_underscore_is_last_value(true); + interpreter->vm().set_underscore_is_last_value(true); s_editor = Line::Editor::construct(); @@ -811,7 +811,7 @@ int main(int argc, char** argv) switch (mode) { case CompleteProperty: { - auto maybe_variable = interpreter->get_variable(variable_name, interpreter->global_object()); + auto maybe_variable = vm->get_variable(variable_name, interpreter->global_object()); if (maybe_variable.is_empty()) { maybe_variable = interpreter->global_object().get(FlyString(variable_name)); if (maybe_variable.is_empty()) diff --git a/Userland/test-js.cpp b/Userland/test-js.cpp index a6b9b11f17b..6c4b1e056cf 100644 --- a/Userland/test-js.cpp +++ b/Userland/test-js.cpp @@ -260,7 +260,7 @@ static Result, ParserError> parse_file(const String& static Optional get_test_results(JS::Interpreter& interpreter) { - auto result = interpreter.get_variable("__TestResults__", interpreter.global_object()); + auto result = interpreter.vm().get_variable("__TestResults__", interpreter.global_object()); auto json_string = JS::JSONObject::stringify_impl(interpreter, interpreter.global_object(), result, JS::js_undefined(), JS::js_undefined()); auto json = JsonValue::from_string(json_string); @@ -310,7 +310,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path) JSFileResult file_result { test_path.substring(m_test_root.length() + 1, test_path.length() - m_test_root.length() - 1) }; // Collect logged messages - auto& arr = interpreter->get_variable("__UserOutput__", interpreter->global_object()).as_array(); + auto& arr = interpreter->vm().get_variable("__UserOutput__", interpreter->global_object()).as_array(); for (auto& entry : arr.indexed_properties()) { auto message = entry.value_and_attributes(&interpreter->global_object()).value; file_result.logged_messages.append(message.to_string_without_side_effects()); @@ -579,7 +579,6 @@ void TestRunner::print_test_results() const int main(int argc, char** argv) { bool print_times = false; - struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_flags = SA_NOCLDWAIT; diff --git a/Userland/test-web.cpp b/Userland/test-web.cpp index 7f493ac6ac2..49f77668e54 100644 --- a/Userland/test-web.cpp +++ b/Userland/test-web.cpp @@ -174,11 +174,13 @@ static void cleanup_and_exit() exit(1); } +#if 0 static void handle_sigabrt(int) { dbg() << "test-web: SIGABRT received, cleaning up."; cleanup_and_exit(); } +#endif static double get_time_in_ms() { @@ -288,7 +290,7 @@ static Result, ParserError> parse_file(const String& static Optional get_test_results(JS::Interpreter& interpreter) { - auto result = interpreter.get_variable("__TestResults__", interpreter.global_object()); + auto result = interpreter.vm().get_variable("__TestResults__", interpreter.global_object()); auto json_string = JS::JSONObject::stringify_impl(interpreter, interpreter.global_object(), result, JS::js_undefined(), JS::js_undefined()); auto json = JsonValue::from_string(json_string); @@ -336,7 +338,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path) // Setup the test on the current page to get "__PageToLoad__". old_interpreter.run(old_interpreter.global_object(), *m_web_test_common); old_interpreter.run(old_interpreter.global_object(), *file_program.value()); - auto page_to_load = URL(old_interpreter.get_variable("__PageToLoad__", old_interpreter.global_object()).as_string().string()); + auto page_to_load = URL(old_interpreter.vm().get_variable("__PageToLoad__", old_interpreter.global_object()).as_string().string()); if (!page_to_load.is_valid()) { printf("Invalid page URL for %s", test_path.characters()); cleanup_and_exit(); @@ -360,7 +362,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path) new_interpreter.run(new_interpreter.global_object(), *m_web_test_common); new_interpreter.run(new_interpreter.global_object(), *file_program.value()); - auto& before_initial_page_load = new_interpreter.get_variable("__BeforeInitialPageLoad__", new_interpreter.global_object()).as_function(); + auto& before_initial_page_load = new_interpreter.vm().get_variable("__BeforeInitialPageLoad__", new_interpreter.global_object()).as_function(); (void)new_interpreter.call(before_initial_page_load, JS::js_undefined()); if (new_interpreter.exception()) new_interpreter.vm().clear_exception(); @@ -370,7 +372,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path) m_page_view->set_document(&parser.document()); // Finally run the test by calling "__AfterInitialPageLoad__" - auto& after_initial_page_load = new_interpreter.get_variable("__AfterInitialPageLoad__", new_interpreter.global_object()).as_function(); + auto& after_initial_page_load = new_interpreter.vm().get_variable("__AfterInitialPageLoad__", new_interpreter.global_object()).as_function(); (void)new_interpreter.call(after_initial_page_load, JS::js_undefined()); if (new_interpreter.exception()) new_interpreter.vm().clear_exception(); @@ -384,7 +386,7 @@ JSFileResult TestRunner::run_file_test(const String& test_path) file_result = { test_path.substring(m_web_test_root.length() + 1, test_path.length() - m_web_test_root.length() - 1) }; // Collect logged messages - auto& arr = new_interpreter.get_variable("__UserOutput__", new_interpreter.global_object()).as_array(); + auto& arr = new_interpreter.vm().get_variable("__UserOutput__", new_interpreter.global_object()).as_array(); for (auto& entry : arr.indexed_properties()) { auto message = entry.value_and_attributes(&new_interpreter.global_object()).value; file_result.logged_messages.append(message.to_string_without_side_effects()); @@ -660,6 +662,7 @@ int main(int argc, char** argv) bool print_times = false; bool show_window = false; +#if 0 struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_flags = SA_NOCLDWAIT; @@ -669,6 +672,7 @@ int main(int argc, char** argv) perror("sigaction"); return 1; } +#endif Core::ArgsParser args_parser; args_parser.add_option(print_times, "Show duration of each test", "show-time", 't');