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)