diff --git a/Userland/Applications/Browser/BrowserConsoleClient.cpp b/Userland/Applications/Browser/BrowserConsoleClient.cpp index e721553fca..6f34daa2cf 100644 --- a/Userland/Applications/Browser/BrowserConsoleClient.cpp +++ b/Userland/Applications/Browser/BrowserConsoleClient.cpp @@ -124,4 +124,25 @@ JS::Value BrowserConsoleClient::count_reset() return JS::js_undefined(); } +JS::Value BrowserConsoleClient::assert_() +{ + auto& vm = this->vm(); + if (!vm.argument(0).to_boolean()) { + StringBuilder html; + if (vm.argument_count() > 1) { + html.append(""); + html.append("Assertion failed:"); + html.append(""); + html.append(" "); + html.append(escape_html_entities(vm.join_arguments(1))); + } else { + html.append(""); + html.append("Assertion failed"); + html.append(""); + } + m_console_widget.print_html(html.string_view()); + } + return JS::js_undefined(); +} + } diff --git a/Userland/Applications/Browser/BrowserConsoleClient.h b/Userland/Applications/Browser/BrowserConsoleClient.h index e87f6e32b0..b0c6fe8a34 100644 --- a/Userland/Applications/Browser/BrowserConsoleClient.h +++ b/Userland/Applications/Browser/BrowserConsoleClient.h @@ -53,6 +53,7 @@ private: virtual JS::Value trace() override; virtual JS::Value count() override; virtual JS::Value count_reset() override; + virtual JS::Value assert_() override; ConsoleWidget& m_console_widget; }; diff --git a/Userland/Libraries/LibJS/Console.cpp b/Userland/Libraries/LibJS/Console.cpp index 797a86b355..082e5a0dc1 100644 --- a/Userland/Libraries/LibJS/Console.cpp +++ b/Userland/Libraries/LibJS/Console.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Emanuele Torre - * Copyright (c) 2020, Linus Groh + * Copyright (c) 2020-2021, Linus Groh * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -118,6 +118,13 @@ Value Console::count_reset() return js_undefined(); } +Value Console::assert_() +{ + if (m_client) + return m_client->assert_(); + return js_undefined(); +} + unsigned Console::counter_increment(String label) { auto value = m_counters.get(label); diff --git a/Userland/Libraries/LibJS/Console.h b/Userland/Libraries/LibJS/Console.h index 600e14e9a1..9894a37696 100644 --- a/Userland/Libraries/LibJS/Console.h +++ b/Userland/Libraries/LibJS/Console.h @@ -57,13 +57,11 @@ public: Value info(); Value log(); Value warn(); - Value clear(); - Value trace(); - Value count(); Value count_reset(); + Value assert_(); unsigned counter_increment(String label); bool counter_reset(String label); @@ -77,7 +75,7 @@ private: class ConsoleClient { public: - ConsoleClient(Console& console) + explicit ConsoleClient(Console& console) : m_console(console) { } @@ -91,6 +89,7 @@ public: virtual Value trace() = 0; virtual Value count() = 0; virtual Value count_reset() = 0; + virtual Value assert_() = 0; protected: virtual ~ConsoleClient() = default; diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index ce4c3807fa..1ecbd49d67 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -71,6 +71,7 @@ namespace JS { P(asUintN) \ P(asin) \ P(asinh) \ + P(assert) \ P(at) \ P(atan) \ P(atan2) \ diff --git a/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp b/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp index 6bf7aafde4..7e4a44497e 100644 --- a/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2020, Linus Groh + * Copyright (c) 2020-2021, Linus Groh * Copyright (c) 2020, Emanuele Torre * All rights reserved. * @@ -50,6 +50,7 @@ void ConsoleObject::initialize(GlobalObject& global_object) define_native_function(vm.names.count, count); define_native_function(vm.names.countReset, count_reset); define_native_function(vm.names.clear, clear); + define_native_function(vm.names.assert, assert_); } ConsoleObject::~ConsoleObject() @@ -101,4 +102,9 @@ JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::clear) return global_object.console().clear(); } +JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::assert_) +{ + return global_object.console().assert_(); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/ConsoleObject.h b/Userland/Libraries/LibJS/Runtime/ConsoleObject.h index 07848aa44f..b1f9c405ab 100644 --- a/Userland/Libraries/LibJS/Runtime/ConsoleObject.h +++ b/Userland/Libraries/LibJS/Runtime/ConsoleObject.h @@ -48,6 +48,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(count); JS_DECLARE_NATIVE_FUNCTION(count_reset); JS_DECLARE_NATIVE_FUNCTION(clear); + JS_DECLARE_NATIVE_FUNCTION(assert_); }; } diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index e2e5aa05af..13a697592a 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -321,10 +321,10 @@ void VM::throw_exception(Exception& exception) unwind(ScopeType::Try); } -String VM::join_arguments() const +String VM::join_arguments(size_t start_index) const { StringBuilder joined_arguments; - for (size_t i = 0; i < argument_count(); ++i) { + for (size_t i = start_index; i < argument_count(); ++i) { joined_arguments.append(argument(i).to_string_without_side_effects().characters()); if (i != argument_count() - 1) joined_arguments.append(' '); diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index d0a928732b..02946cf9c4 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -222,7 +222,7 @@ public: Value construct(Function&, Function& new_target, Optional arguments, GlobalObject&); - String join_arguments() const; + String join_arguments(size_t start_index = 0) const; Value resolve_this_binding(GlobalObject&) const; const ScopeObject* find_this_scope() const; diff --git a/Userland/Services/WebContent/WebContentConsoleClient.cpp b/Userland/Services/WebContent/WebContentConsoleClient.cpp index e766cdfacf..c0df9db025 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.cpp +++ b/Userland/Services/WebContent/WebContentConsoleClient.cpp @@ -168,4 +168,25 @@ JS::Value WebContentConsoleClient::count_reset() return JS::js_undefined(); } +JS::Value WebContentConsoleClient::assert_() +{ + auto& vm = this->vm(); + if (!vm.argument(0).to_boolean()) { + StringBuilder html; + if (vm.argument_count() > 1) { + html.append(""); + html.append("Assertion failed:"); + html.append(""); + html.append(" "); + html.append(escape_html_entities(vm.join_arguments(1))); + } else { + html.append(""); + html.append("Assertion failed"); + html.append(""); + } + print_html(html.string_view()); + } + return JS::js_undefined(); +} + } diff --git a/Userland/Services/WebContent/WebContentConsoleClient.h b/Userland/Services/WebContent/WebContentConsoleClient.h index 614e15a9d5..ddaa6007d8 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.h +++ b/Userland/Services/WebContent/WebContentConsoleClient.h @@ -56,6 +56,7 @@ private: virtual JS::Value trace() override; virtual JS::Value count() override; virtual JS::Value count_reset() override; + virtual JS::Value assert_() override; ClientConnection& m_client; WeakPtr m_interpreter; diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index 5cfb28e4b1..567a29135b 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -650,32 +650,38 @@ public: outln("{}", vm().join_arguments()); return JS::js_undefined(); } + virtual JS::Value info() override { outln("(i) {}", vm().join_arguments()); return JS::js_undefined(); } + virtual JS::Value debug() override { outln("\033[36;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } + virtual JS::Value warn() override { outln("\033[33;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } + virtual JS::Value error() override { outln("\033[31;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } + virtual JS::Value clear() override { out("\033[3J\033[H\033[2J"); fflush(stdout); return JS::js_undefined(); } + virtual JS::Value trace() override { outln("{}", vm().join_arguments()); @@ -687,6 +693,7 @@ public: } return JS::js_undefined(); } + virtual JS::Value count() override { auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default"; @@ -694,6 +701,7 @@ public: outln("{}: {}", label, counter_value); return JS::js_undefined(); } + virtual JS::Value count_reset() override { auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default"; @@ -703,6 +711,20 @@ public: outln("\033[33;1m\"{}\" doesn't have a count\033[0m", label); return JS::js_undefined(); } + + virtual JS::Value assert_() override + { + auto& vm = this->vm(); + if (!vm.argument(0).to_boolean()) { + if (vm.argument_count() > 1) { + out("\033[31;1mAssertion failed:\033[0m"); + outln(" {}", vm.join_arguments(1)); + } else { + outln("\033[31;1mAssertion failed\033[0m"); + } + } + return JS::js_undefined(); + } }; int main(int argc, char** argv)