Serenity Operating System
1/*
2 * Copyright (c) 2020, Emanuele Torre <torreemanuele6@gmail.com>
3 * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <AK/Function.h>
11#include <AK/HashMap.h>
12#include <AK/Noncopyable.h>
13#include <AK/String.h>
14#include <AK/Vector.h>
15#include <LibCore/ElapsedTimer.h>
16#include <LibJS/Forward.h>
17#include <LibJS/Runtime/Value.h>
18
19namespace JS {
20
21class ConsoleClient;
22
23// https://console.spec.whatwg.org
24class Console {
25 AK_MAKE_NONCOPYABLE(Console);
26 AK_MAKE_NONMOVABLE(Console);
27
28public:
29 // These are not really levels, but that's the term used in the spec.
30 enum class LogLevel {
31 Assert,
32 Count,
33 CountReset,
34 Debug,
35 Dir,
36 DirXML,
37 Error,
38 Group,
39 GroupCollapsed,
40 Info,
41 Log,
42 TimeEnd,
43 TimeLog,
44 Trace,
45 Warn,
46 };
47
48 struct Group {
49 String label;
50 };
51
52 struct Trace {
53 String label;
54 Vector<String> stack;
55 };
56
57 explicit Console(Realm&);
58
59 void set_client(ConsoleClient& client) { m_client = &client; }
60
61 Realm& realm() const { return m_realm; }
62
63 MarkedVector<Value> vm_arguments();
64
65 HashMap<String, unsigned>& counters() { return m_counters; }
66 HashMap<String, unsigned> const& counters() const { return m_counters; }
67
68 ThrowCompletionOr<Value> debug();
69 ThrowCompletionOr<Value> error();
70 ThrowCompletionOr<Value> info();
71 ThrowCompletionOr<Value> log();
72 ThrowCompletionOr<Value> warn();
73 Value clear();
74 ThrowCompletionOr<Value> trace();
75 ThrowCompletionOr<Value> count();
76 ThrowCompletionOr<Value> count_reset();
77 ThrowCompletionOr<Value> assert_();
78 ThrowCompletionOr<Value> group();
79 ThrowCompletionOr<Value> group_collapsed();
80 ThrowCompletionOr<Value> group_end();
81 ThrowCompletionOr<Value> time();
82 ThrowCompletionOr<Value> time_log();
83 ThrowCompletionOr<Value> time_end();
84
85 void output_debug_message(LogLevel log_level, String const& output) const;
86 void report_exception(JS::Error const&, bool) const;
87
88private:
89 ThrowCompletionOr<String> value_vector_to_string(MarkedVector<Value> const&);
90 ThrowCompletionOr<String> format_time_since(Core::ElapsedTimer timer);
91
92 Realm& m_realm;
93 ConsoleClient* m_client { nullptr };
94
95 HashMap<String, unsigned> m_counters;
96 HashMap<String, Core::ElapsedTimer> m_timer_table;
97 Vector<Group> m_group_stack;
98};
99
100class ConsoleClient {
101public:
102 explicit ConsoleClient(Console& console)
103 : m_console(console)
104 {
105 }
106
107 using PrinterArguments = Variant<Console::Group, Console::Trace, MarkedVector<Value>>;
108
109 ThrowCompletionOr<Value> logger(Console::LogLevel log_level, MarkedVector<Value> const& args);
110 ThrowCompletionOr<MarkedVector<Value>> formatter(MarkedVector<Value> const& args);
111 virtual ThrowCompletionOr<Value> printer(Console::LogLevel log_level, PrinterArguments) = 0;
112
113 virtual void add_css_style_to_current_message(StringView) { }
114 virtual void report_exception(JS::Error const&, bool) { }
115
116 virtual void clear() = 0;
117 virtual void end_group() = 0;
118
119 ThrowCompletionOr<String> generically_format_values(MarkedVector<Value> const&);
120
121protected:
122 virtual ~ConsoleClient() = default;
123
124 Console& m_console;
125};
126
127}