mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 07:58:11 +00:00
LibJS+Userland: Port the JS Console object and direct callers to String
This commit is contained in:
parent
8f9659a549
commit
3b4879d29b
5 changed files with 125 additions and 84 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <LibJS/Runtime/AbstractOperations.h>
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/StringConstructor.h>
|
#include <LibJS/Runtime/StringConstructor.h>
|
||||||
#include <LibJS/Runtime/Temporal/Duration.h>
|
#include <LibJS/Runtime/Temporal/Duration.h>
|
||||||
|
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
@ -98,29 +99,37 @@ ThrowCompletionOr<Value> Console::trace()
|
||||||
auto& execution_context_stack = vm.execution_context_stack();
|
auto& execution_context_stack = vm.execution_context_stack();
|
||||||
// NOTE: -2 to skip the console.trace() execution context
|
// NOTE: -2 to skip the console.trace() execution context
|
||||||
for (ssize_t i = execution_context_stack.size() - 2; i >= 0; --i) {
|
for (ssize_t i = execution_context_stack.size() - 2; i >= 0; --i) {
|
||||||
auto& function_name = execution_context_stack[i]->function_name;
|
auto const& function_name = execution_context_stack[i]->function_name;
|
||||||
trace.stack.append(function_name.is_empty() ? "<anonymous>" : function_name);
|
trace.stack.append(function_name.is_empty()
|
||||||
|
? TRY_OR_THROW_OOM(vm, String::from_utf8("<anonymous>"sv))
|
||||||
|
: TRY_OR_THROW_OOM(vm, String::from_deprecated_string(function_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Optionally, let formattedData be the result of Formatter(data), and incorporate formattedData as a label for trace.
|
// 2. Optionally, let formattedData be the result of Formatter(data), and incorporate formattedData as a label for trace.
|
||||||
if (vm.argument_count() > 0) {
|
if (vm.argument_count() > 0) {
|
||||||
StringBuilder builder;
|
|
||||||
auto data = vm_arguments();
|
auto data = vm_arguments();
|
||||||
auto formatted_data = TRY(m_client->formatter(data));
|
auto formatted_data = TRY(m_client->formatter(data));
|
||||||
trace.label = TRY(value_vector_to_deprecated_string(formatted_data));
|
trace.label = TRY(value_vector_to_string(formatted_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Perform Printer("trace", « trace »).
|
// 3. Perform Printer("trace", « trace »).
|
||||||
return m_client->printer(Console::LogLevel::Trace, trace);
|
return m_client->printer(Console::LogLevel::Trace, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ThrowCompletionOr<String> label_or_fallback(VM& vm, StringView fallback)
|
||||||
|
{
|
||||||
|
return vm.argument_count() > 0
|
||||||
|
? vm.argument(0).to_string(vm)
|
||||||
|
: TRY_OR_THROW_OOM(vm, String::from_utf8(fallback));
|
||||||
|
}
|
||||||
|
|
||||||
// 1.2.1. count(label), https://console.spec.whatwg.org/#count
|
// 1.2.1. count(label), https://console.spec.whatwg.org/#count
|
||||||
ThrowCompletionOr<Value> Console::count()
|
ThrowCompletionOr<Value> Console::count()
|
||||||
{
|
{
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-count
|
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-count
|
||||||
auto label = vm.argument_count() ? TRY(vm.argument(0).to_deprecated_string(vm)) : "default";
|
auto label = TRY(label_or_fallback(vm, "default"sv));
|
||||||
|
|
||||||
// 1. Let map be the associated count map.
|
// 1. Let map be the associated count map.
|
||||||
auto& map = m_counters;
|
auto& map = m_counters;
|
||||||
|
@ -135,11 +144,11 @@ ThrowCompletionOr<Value> Console::count()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and ToString(map[label]).
|
// 4. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and ToString(map[label]).
|
||||||
DeprecatedString concat = DeprecatedString::formatted("{}: {}", label, map.get(label).value());
|
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, map.get(label).value()));
|
||||||
|
|
||||||
// 5. Perform Logger("count", « concat »).
|
// 5. Perform Logger("count", « concat »).
|
||||||
MarkedVector<Value> concat_as_vector { vm.heap() };
|
MarkedVector<Value> concat_as_vector { vm.heap() };
|
||||||
concat_as_vector.append(PrimitiveString::create(vm, concat));
|
concat_as_vector.append(PrimitiveString::create(vm, move(concat)));
|
||||||
if (m_client)
|
if (m_client)
|
||||||
TRY(m_client->logger(LogLevel::Count, concat_as_vector));
|
TRY(m_client->logger(LogLevel::Count, concat_as_vector));
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
@ -151,7 +160,7 @@ ThrowCompletionOr<Value> Console::count_reset()
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-countreset
|
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-countreset
|
||||||
auto label = vm.argument_count() ? TRY(vm.argument(0).to_deprecated_string(vm)) : "default";
|
auto label = TRY(label_or_fallback(vm, "default"sv));
|
||||||
|
|
||||||
// 1. Let map be the associated count map.
|
// 1. Let map be the associated count map.
|
||||||
auto& map = m_counters;
|
auto& map = m_counters;
|
||||||
|
@ -164,10 +173,10 @@ ThrowCompletionOr<Value> Console::count_reset()
|
||||||
else {
|
else {
|
||||||
// 1. Let message be a string without any formatting specifiers indicating generically
|
// 1. Let message be a string without any formatting specifiers indicating generically
|
||||||
// that the given label does not have an associated count.
|
// that the given label does not have an associated count.
|
||||||
auto message = DeprecatedString::formatted("\"{}\" doesn't have a count", label);
|
auto message = TRY_OR_THROW_OOM(vm, String::formatted("\"{}\" doesn't have a count", label));
|
||||||
// 2. Perform Logger("countReset", « message »);
|
// 2. Perform Logger("countReset", « message »);
|
||||||
MarkedVector<Value> message_as_vector { vm.heap() };
|
MarkedVector<Value> message_as_vector { vm.heap() };
|
||||||
message_as_vector.append(PrimitiveString::create(vm, message));
|
message_as_vector.append(PrimitiveString::create(vm, move(message)));
|
||||||
if (m_client)
|
if (m_client)
|
||||||
TRY(m_client->logger(LogLevel::CountReset, message_as_vector));
|
TRY(m_client->logger(LogLevel::CountReset, message_as_vector));
|
||||||
}
|
}
|
||||||
|
@ -212,9 +221,9 @@ ThrowCompletionOr<Value> Console::assert_()
|
||||||
// 3. Otherwise:
|
// 3. Otherwise:
|
||||||
else {
|
else {
|
||||||
// 1. Let concat be the concatenation of message, U+003A (:), U+0020 SPACE, and first.
|
// 1. Let concat be the concatenation of message, U+003A (:), U+0020 SPACE, and first.
|
||||||
auto concat = PrimitiveString::create(vm, DeprecatedString::formatted("{}: {}", TRY(message->deprecated_string()), first.to_deprecated_string(vm).value()));
|
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", TRY(message->utf8_string()), MUST(first.to_string(vm))));
|
||||||
// 2. Set data[0] to concat.
|
// 2. Set data[0] to concat.
|
||||||
data[0] = concat;
|
data[0] = PrimitiveString::create(vm, move(concat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,19 +236,21 @@ ThrowCompletionOr<Value> Console::assert_()
|
||||||
// 1.3.1. group(...data), https://console.spec.whatwg.org/#group
|
// 1.3.1. group(...data), https://console.spec.whatwg.org/#group
|
||||||
ThrowCompletionOr<Value> Console::group()
|
ThrowCompletionOr<Value> Console::group()
|
||||||
{
|
{
|
||||||
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// 1. Let group be a new group.
|
// 1. Let group be a new group.
|
||||||
Group group;
|
Group group;
|
||||||
|
|
||||||
// 2. If data is not empty, let groupLabel be the result of Formatter(data).
|
// 2. If data is not empty, let groupLabel be the result of Formatter(data).
|
||||||
DeprecatedString group_label;
|
String group_label {};
|
||||||
auto data = vm_arguments();
|
auto data = vm_arguments();
|
||||||
if (!data.is_empty()) {
|
if (!data.is_empty()) {
|
||||||
auto formatted_data = TRY(m_client->formatter(data));
|
auto formatted_data = TRY(m_client->formatter(data));
|
||||||
group_label = TRY(value_vector_to_deprecated_string(formatted_data));
|
group_label = TRY(value_vector_to_string(formatted_data));
|
||||||
}
|
}
|
||||||
// ... Otherwise, let groupLabel be an implementation-chosen label representing a group.
|
// ... Otherwise, let groupLabel be an implementation-chosen label representing a group.
|
||||||
else {
|
else {
|
||||||
group_label = "Group";
|
group_label = TRY_OR_THROW_OOM(vm, String::from_utf8("Group"sv));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Incorporate groupLabel as a label for group.
|
// 3. Incorporate groupLabel as a label for group.
|
||||||
|
@ -261,19 +272,21 @@ ThrowCompletionOr<Value> Console::group()
|
||||||
// 1.3.2. groupCollapsed(...data), https://console.spec.whatwg.org/#groupcollapsed
|
// 1.3.2. groupCollapsed(...data), https://console.spec.whatwg.org/#groupcollapsed
|
||||||
ThrowCompletionOr<Value> Console::group_collapsed()
|
ThrowCompletionOr<Value> Console::group_collapsed()
|
||||||
{
|
{
|
||||||
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// 1. Let group be a new group.
|
// 1. Let group be a new group.
|
||||||
Group group;
|
Group group;
|
||||||
|
|
||||||
// 2. If data is not empty, let groupLabel be the result of Formatter(data).
|
// 2. If data is not empty, let groupLabel be the result of Formatter(data).
|
||||||
DeprecatedString group_label;
|
String group_label {};
|
||||||
auto data = vm_arguments();
|
auto data = vm_arguments();
|
||||||
if (!data.is_empty()) {
|
if (!data.is_empty()) {
|
||||||
auto formatted_data = TRY(m_client->formatter(data));
|
auto formatted_data = TRY(m_client->formatter(data));
|
||||||
group_label = TRY(value_vector_to_deprecated_string(formatted_data));
|
group_label = TRY(value_vector_to_string(formatted_data));
|
||||||
}
|
}
|
||||||
// ... Otherwise, let groupLabel be an implementation-chosen label representing a group.
|
// ... Otherwise, let groupLabel be an implementation-chosen label representing a group.
|
||||||
else {
|
else {
|
||||||
group_label = "Group";
|
group_label = TRY_OR_THROW_OOM(vm, String::from_utf8("Group"sv));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Incorporate groupLabel as a label for group.
|
// 3. Incorporate groupLabel as a label for group.
|
||||||
|
@ -312,14 +325,17 @@ ThrowCompletionOr<Value> Console::time()
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-time
|
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-time
|
||||||
auto label = vm.argument_count() ? TRY(vm.argument(0).to_deprecated_string(vm)) : "default";
|
auto label = TRY(label_or_fallback(vm, "default"sv));
|
||||||
|
|
||||||
// 1. If the associated timer table contains an entry with key label, return, optionally reporting
|
// 1. If the associated timer table contains an entry with key label, return, optionally reporting
|
||||||
// a warning to the console indicating that a timer with label `label` has already been started.
|
// a warning to the console indicating that a timer with label `label` has already been started.
|
||||||
if (m_timer_table.contains(label)) {
|
if (m_timer_table.contains(label)) {
|
||||||
if (m_client) {
|
if (m_client) {
|
||||||
MarkedVector<Value> timer_already_exists_warning_message_as_vector { vm.heap() };
|
MarkedVector<Value> timer_already_exists_warning_message_as_vector { vm.heap() };
|
||||||
timer_already_exists_warning_message_as_vector.append(PrimitiveString::create(vm, DeprecatedString::formatted("Timer '{}' already exists.", label)));
|
|
||||||
|
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' already exists.", label));
|
||||||
|
timer_already_exists_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
|
||||||
|
|
||||||
TRY(m_client->printer(LogLevel::Warn, move(timer_already_exists_warning_message_as_vector)));
|
TRY(m_client->printer(LogLevel::Warn, move(timer_already_exists_warning_message_as_vector)));
|
||||||
}
|
}
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
@ -336,7 +352,7 @@ ThrowCompletionOr<Value> Console::time_log()
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-timelog
|
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-timelog
|
||||||
auto label = vm.argument_count() ? TRY(vm.argument(0).to_deprecated_string(vm)) : "default";
|
auto label = TRY(label_or_fallback(vm, "default"sv));
|
||||||
|
|
||||||
// 1. Let timerTable be the associated timer table.
|
// 1. Let timerTable be the associated timer table.
|
||||||
|
|
||||||
|
@ -347,7 +363,10 @@ ThrowCompletionOr<Value> Console::time_log()
|
||||||
if (maybe_start_time == m_timer_table.end()) {
|
if (maybe_start_time == m_timer_table.end()) {
|
||||||
if (m_client) {
|
if (m_client) {
|
||||||
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
|
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
|
||||||
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, DeprecatedString::formatted("Timer '{}' does not exist.", label)));
|
|
||||||
|
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label));
|
||||||
|
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
|
||||||
|
|
||||||
TRY(m_client->printer(LogLevel::Warn, move(timer_does_not_exist_warning_message_as_vector)));
|
TRY(m_client->printer(LogLevel::Warn, move(timer_does_not_exist_warning_message_as_vector)));
|
||||||
}
|
}
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
@ -358,12 +377,12 @@ ThrowCompletionOr<Value> Console::time_log()
|
||||||
auto duration = TRY(format_time_since(start_time));
|
auto duration = TRY(format_time_since(start_time));
|
||||||
|
|
||||||
// 4. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and duration.
|
// 4. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and duration.
|
||||||
auto concat = DeprecatedString::formatted("{}: {}", label, duration);
|
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, duration));
|
||||||
|
|
||||||
// 5. Prepend concat to data.
|
// 5. Prepend concat to data.
|
||||||
MarkedVector<Value> data { vm.heap() };
|
MarkedVector<Value> data { vm.heap() };
|
||||||
data.ensure_capacity(vm.argument_count());
|
data.ensure_capacity(vm.argument_count());
|
||||||
data.append(PrimitiveString::create(vm, concat));
|
data.append(PrimitiveString::create(vm, move(concat)));
|
||||||
for (size_t i = 1; i < vm.argument_count(); ++i)
|
for (size_t i = 1; i < vm.argument_count(); ++i)
|
||||||
data.append(vm.argument(i));
|
data.append(vm.argument(i));
|
||||||
|
|
||||||
|
@ -379,7 +398,7 @@ ThrowCompletionOr<Value> Console::time_end()
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-timeend
|
// NOTE: "default" is the default value in the IDL. https://console.spec.whatwg.org/#ref-for-timeend
|
||||||
auto label = vm.argument_count() ? TRY(vm.argument(0).to_deprecated_string(vm)) : "default";
|
auto label = TRY(label_or_fallback(vm, "default"sv));
|
||||||
|
|
||||||
// 1. Let timerTable be the associated timer table.
|
// 1. Let timerTable be the associated timer table.
|
||||||
|
|
||||||
|
@ -390,7 +409,10 @@ ThrowCompletionOr<Value> Console::time_end()
|
||||||
if (maybe_start_time == m_timer_table.end()) {
|
if (maybe_start_time == m_timer_table.end()) {
|
||||||
if (m_client) {
|
if (m_client) {
|
||||||
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
|
MarkedVector<Value> timer_does_not_exist_warning_message_as_vector { vm.heap() };
|
||||||
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, DeprecatedString::formatted("Timer '{}' does not exist.", label)));
|
|
||||||
|
auto message = TRY_OR_THROW_OOM(vm, String::formatted("Timer '{}' does not exist.", label));
|
||||||
|
timer_does_not_exist_warning_message_as_vector.append(PrimitiveString::create(vm, move(message)));
|
||||||
|
|
||||||
TRY(m_client->printer(LogLevel::Warn, move(timer_does_not_exist_warning_message_as_vector)));
|
TRY(m_client->printer(LogLevel::Warn, move(timer_does_not_exist_warning_message_as_vector)));
|
||||||
}
|
}
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
@ -404,12 +426,12 @@ ThrowCompletionOr<Value> Console::time_end()
|
||||||
auto duration = TRY(format_time_since(start_time));
|
auto duration = TRY(format_time_since(start_time));
|
||||||
|
|
||||||
// 5. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and duration.
|
// 5. Let concat be the concatenation of label, U+003A (:), U+0020 SPACE, and duration.
|
||||||
auto concat = DeprecatedString::formatted("{}: {}", label, duration);
|
auto concat = TRY_OR_THROW_OOM(vm, String::formatted("{}: {}", label, duration));
|
||||||
|
|
||||||
// 6. Perform Printer("timeEnd", « concat »).
|
// 6. Perform Printer("timeEnd", « concat »).
|
||||||
if (m_client) {
|
if (m_client) {
|
||||||
MarkedVector<Value> concat_as_vector { vm.heap() };
|
MarkedVector<Value> concat_as_vector { vm.heap() };
|
||||||
concat_as_vector.append(PrimitiveString::create(vm, concat));
|
concat_as_vector.append(PrimitiveString::create(vm, move(concat)));
|
||||||
TRY(m_client->printer(LogLevel::TimeEnd, move(concat_as_vector)));
|
TRY(m_client->printer(LogLevel::TimeEnd, move(concat_as_vector)));
|
||||||
}
|
}
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
@ -427,7 +449,7 @@ MarkedVector<Value> Console::vm_arguments()
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::output_debug_message(LogLevel log_level, DeprecatedString const& output) const
|
void Console::output_debug_message(LogLevel log_level, String const& output) const
|
||||||
{
|
{
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
case Console::LogLevel::Debug:
|
case Console::LogLevel::Debug:
|
||||||
|
@ -457,43 +479,49 @@ void Console::report_exception(JS::Error const& exception, bool in_promise) cons
|
||||||
m_client->report_exception(exception, in_promise);
|
m_client->report_exception(exception, in_promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowCompletionOr<DeprecatedString> Console::value_vector_to_deprecated_string(MarkedVector<Value> const& values)
|
ThrowCompletionOr<String> Console::value_vector_to_string(MarkedVector<Value> const& values)
|
||||||
{
|
{
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
StringBuilder builder;
|
ThrowableStringBuilder builder(vm);
|
||||||
|
|
||||||
for (auto const& item : values) {
|
for (auto const& item : values) {
|
||||||
if (!builder.is_empty())
|
if (!builder.is_empty())
|
||||||
builder.append(' ');
|
MUST_OR_THROW_OOM(builder.append(' '));
|
||||||
builder.append(TRY(item.to_deprecated_string(vm)));
|
|
||||||
|
MUST_OR_THROW_OOM(builder.append(TRY(item.to_string(vm))));
|
||||||
}
|
}
|
||||||
return builder.to_deprecated_string();
|
|
||||||
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowCompletionOr<DeprecatedString> Console::format_time_since(Core::ElapsedTimer timer)
|
ThrowCompletionOr<String> Console::format_time_since(Core::ElapsedTimer timer)
|
||||||
{
|
{
|
||||||
auto& vm = realm().vm();
|
auto& vm = realm().vm();
|
||||||
|
|
||||||
auto elapsed_ms = timer.elapsed_time().to_milliseconds();
|
auto elapsed_ms = timer.elapsed_time().to_milliseconds();
|
||||||
auto duration = TRY(Temporal::balance_duration(vm, 0, 0, 0, 0, elapsed_ms, 0, "0"_sbigint, "year"sv));
|
auto duration = TRY(Temporal::balance_duration(vm, 0, 0, 0, 0, elapsed_ms, 0, "0"_sbigint, "year"sv));
|
||||||
|
|
||||||
auto append = [&](StringBuilder& builder, auto format, auto... number) {
|
auto append = [&](ThrowableStringBuilder& builder, auto format, auto number) -> ThrowCompletionOr<void> {
|
||||||
if (!builder.is_empty())
|
if (!builder.is_empty())
|
||||||
builder.append(' ');
|
MUST_OR_THROW_OOM(builder.append(' '));
|
||||||
builder.appendff(format, number...);
|
MUST_OR_THROW_OOM(builder.appendff(format, number));
|
||||||
|
return {};
|
||||||
};
|
};
|
||||||
StringBuilder builder;
|
|
||||||
|
ThrowableStringBuilder builder(vm);
|
||||||
|
|
||||||
if (duration.days > 0)
|
if (duration.days > 0)
|
||||||
append(builder, "{:.0} day(s)"sv, duration.days);
|
MUST_OR_THROW_OOM(append(builder, "{:.0} day(s)"sv, duration.days));
|
||||||
if (duration.hours > 0)
|
if (duration.hours > 0)
|
||||||
append(builder, "{:.0} hour(s)"sv, duration.hours);
|
MUST_OR_THROW_OOM(append(builder, "{:.0} hour(s)"sv, duration.hours));
|
||||||
if (duration.minutes > 0)
|
if (duration.minutes > 0)
|
||||||
append(builder, "{:.0} minute(s)"sv, duration.minutes);
|
MUST_OR_THROW_OOM(append(builder, "{:.0} minute(s)"sv, duration.minutes));
|
||||||
if (duration.seconds > 0 || duration.milliseconds > 0) {
|
if (duration.seconds > 0 || duration.milliseconds > 0) {
|
||||||
double combined_seconds = duration.seconds + (0.001 * duration.milliseconds);
|
double combined_seconds = duration.seconds + (0.001 * duration.milliseconds);
|
||||||
append(builder, "{:.3} seconds"sv, combined_seconds);
|
MUST_OR_THROW_OOM(append(builder, "{:.3} seconds"sv, combined_seconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.to_deprecated_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.1. Logger(logLevel, args), https://console.spec.whatwg.org/#logger
|
// 2.1. Logger(logLevel, args), https://console.spec.whatwg.org/#logger
|
||||||
|
@ -539,7 +567,7 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val
|
||||||
return args;
|
return args;
|
||||||
|
|
||||||
// 2. Let target be the first element of args.
|
// 2. Let target be the first element of args.
|
||||||
auto target = (!args.is_empty()) ? TRY(args.first().to_deprecated_string(vm)) : "";
|
auto target = (!args.is_empty()) ? TRY(args.first().to_string(vm)) : String {};
|
||||||
|
|
||||||
// 3. Let current be the second element of args.
|
// 3. Let current be the second element of args.
|
||||||
auto current = (args.size() > 1) ? args[1] : js_undefined();
|
auto current = (args.size() > 1) ? args[1] : js_undefined();
|
||||||
|
@ -621,19 +649,19 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val
|
||||||
// 6. TODO: process %c
|
// 6. TODO: process %c
|
||||||
else if (specifier == "%c"sv) {
|
else if (specifier == "%c"sv) {
|
||||||
// NOTE: This has no spec yet. `%c` specifiers treat the argument as CSS styling for the log message.
|
// NOTE: This has no spec yet. `%c` specifiers treat the argument as CSS styling for the log message.
|
||||||
add_css_style_to_current_message(TRY(current.to_deprecated_string(vm)));
|
add_css_style_to_current_message(TRY(current.to_string(vm)));
|
||||||
converted = PrimitiveString::create(vm, String {});
|
converted = PrimitiveString::create(vm, String {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. If any of the previous steps set converted, replace specifier in target with converted.
|
// 7. If any of the previous steps set converted, replace specifier in target with converted.
|
||||||
if (converted.has_value())
|
if (converted.has_value())
|
||||||
target = target.replace(specifier, TRY(converted->to_deprecated_string(vm)), ReplaceMode::FirstOnly);
|
target = TRY_OR_THROW_OOM(vm, target.replace(specifier, TRY(converted->to_string(vm)), ReplaceMode::FirstOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Let result be a list containing target together with the elements of args starting from the third onward.
|
// 7. Let result be a list containing target together with the elements of args starting from the third onward.
|
||||||
MarkedVector<Value> result { vm.heap() };
|
MarkedVector<Value> result { vm.heap() };
|
||||||
result.ensure_capacity(args.size() - 1);
|
result.ensure_capacity(args.size() - 1);
|
||||||
result.empend(PrimitiveString::create(vm, target));
|
result.empend(PrimitiveString::create(vm, move(target)));
|
||||||
for (size_t i = 2; i < args.size(); ++i)
|
for (size_t i = 2; i < args.size(); ++i)
|
||||||
result.unchecked_append(args[i]);
|
result.unchecked_append(args[i]);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/Noncopyable.h>
|
#include <AK/Noncopyable.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibCore/ElapsedTimer.h>
|
#include <LibCore/ElapsedTimer.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
|
@ -45,12 +46,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Group {
|
struct Group {
|
||||||
DeprecatedString label;
|
String label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Trace {
|
struct Trace {
|
||||||
DeprecatedString label;
|
String label;
|
||||||
Vector<DeprecatedString> stack;
|
Vector<String> stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Console(Realm&);
|
explicit Console(Realm&);
|
||||||
|
@ -61,8 +62,8 @@ public:
|
||||||
|
|
||||||
MarkedVector<Value> vm_arguments();
|
MarkedVector<Value> vm_arguments();
|
||||||
|
|
||||||
HashMap<DeprecatedString, unsigned>& counters() { return m_counters; }
|
HashMap<String, unsigned>& counters() { return m_counters; }
|
||||||
HashMap<DeprecatedString, unsigned> const& counters() const { return m_counters; }
|
HashMap<String, unsigned> const& counters() const { return m_counters; }
|
||||||
|
|
||||||
ThrowCompletionOr<Value> debug();
|
ThrowCompletionOr<Value> debug();
|
||||||
ThrowCompletionOr<Value> error();
|
ThrowCompletionOr<Value> error();
|
||||||
|
@ -81,18 +82,18 @@ public:
|
||||||
ThrowCompletionOr<Value> time_log();
|
ThrowCompletionOr<Value> time_log();
|
||||||
ThrowCompletionOr<Value> time_end();
|
ThrowCompletionOr<Value> time_end();
|
||||||
|
|
||||||
void output_debug_message(LogLevel log_level, DeprecatedString const& output) const;
|
void output_debug_message(LogLevel log_level, String const& output) const;
|
||||||
void report_exception(JS::Error const&, bool) const;
|
void report_exception(JS::Error const&, bool) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ThrowCompletionOr<DeprecatedString> value_vector_to_deprecated_string(MarkedVector<Value> const&);
|
ThrowCompletionOr<String> value_vector_to_string(MarkedVector<Value> const&);
|
||||||
ThrowCompletionOr<DeprecatedString> format_time_since(Core::ElapsedTimer timer);
|
ThrowCompletionOr<String> format_time_since(Core::ElapsedTimer timer);
|
||||||
|
|
||||||
Realm& m_realm;
|
Realm& m_realm;
|
||||||
ConsoleClient* m_client { nullptr };
|
ConsoleClient* m_client { nullptr };
|
||||||
|
|
||||||
HashMap<DeprecatedString, unsigned> m_counters;
|
HashMap<String, unsigned> m_counters;
|
||||||
HashMap<DeprecatedString, Core::ElapsedTimer> m_timer_table;
|
HashMap<String, Core::ElapsedTimer> m_timer_table;
|
||||||
Vector<Group> m_group_stack;
|
Vector<Group> m_group_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include <LibJS/Heap/MarkedVector.h>
|
#include <LibJS/Heap/MarkedVector.h>
|
||||||
#include <LibJS/Runtime/Completion.h>
|
#include <LibJS/Runtime/Completion.h>
|
||||||
|
#include <LibJS/Runtime/Realm.h>
|
||||||
|
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||||
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibWeb/HTML/WorkerDebugConsoleClient.h>
|
#include <LibWeb/HTML/WorkerDebugConsoleClient.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
@ -31,16 +34,18 @@ void WorkerDebugConsoleClient::end_group()
|
||||||
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
||||||
JS::ThrowCompletionOr<JS::Value> WorkerDebugConsoleClient::printer(JS::Console::LogLevel log_level, PrinterArguments arguments)
|
JS::ThrowCompletionOr<JS::Value> WorkerDebugConsoleClient::printer(JS::Console::LogLevel log_level, PrinterArguments arguments)
|
||||||
{
|
{
|
||||||
DeprecatedString indent = DeprecatedString::repeated(" "sv, m_group_stack_depth);
|
auto& vm = m_console.realm().vm();
|
||||||
|
|
||||||
|
auto indent = TRY_OR_THROW_OOM(vm, String::repeated(' ', m_group_stack_depth * 2));
|
||||||
|
|
||||||
if (log_level == JS::Console::LogLevel::Trace) {
|
if (log_level == JS::Console::LogLevel::Trace) {
|
||||||
auto trace = arguments.get<JS::Console::Trace>();
|
auto trace = arguments.get<JS::Console::Trace>();
|
||||||
StringBuilder builder;
|
JS::ThrowableStringBuilder builder(vm);
|
||||||
if (!trace.label.is_empty())
|
if (!trace.label.is_empty())
|
||||||
builder.appendff("{}\033[36;1m{}\033[0m\n", indent, trace.label);
|
MUST_OR_THROW_OOM(builder.appendff("{}\033[36;1m{}\033[0m\n", indent, trace.label));
|
||||||
|
|
||||||
for (auto& function_name : trace.stack)
|
for (auto& function_name : trace.stack)
|
||||||
builder.appendff("{}-> {}\n", indent, function_name);
|
MUST_OR_THROW_OOM(builder.appendff("{}-> {}\n", indent, function_name));
|
||||||
|
|
||||||
dbgln("{}", builder.string_view());
|
dbgln("{}", builder.string_view());
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
|
@ -53,7 +58,7 @@ JS::ThrowCompletionOr<JS::Value> WorkerDebugConsoleClient::printer(JS::Console::
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto output = DeprecatedString::join(' ', arguments.get<JS::MarkedVector<JS::Value>>());
|
auto output = TRY_OR_THROW_OOM(vm, String::join(' ', arguments.get<JS::MarkedVector<JS::Value>>()));
|
||||||
m_console.output_debug_message(log_level, output);
|
m_console.output_debug_message(log_level, output);
|
||||||
|
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include <LibJS/MarkupGenerator.h>
|
#include <LibJS/MarkupGenerator.h>
|
||||||
#include <LibJS/Runtime/AbstractOperations.h>
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/ObjectEnvironment.h>
|
#include <LibJS/Runtime/ObjectEnvironment.h>
|
||||||
|
#include <LibJS/Runtime/Realm.h>
|
||||||
|
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||||
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibWeb/HTML/PolicyContainers.h>
|
#include <LibWeb/HTML/PolicyContainers.h>
|
||||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||||
|
@ -129,19 +132,21 @@ void WebContentConsoleClient::clear()
|
||||||
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
||||||
JS::ThrowCompletionOr<JS::Value> WebContentConsoleClient::printer(JS::Console::LogLevel log_level, PrinterArguments arguments)
|
JS::ThrowCompletionOr<JS::Value> WebContentConsoleClient::printer(JS::Console::LogLevel log_level, PrinterArguments arguments)
|
||||||
{
|
{
|
||||||
|
auto& vm = m_console.realm().vm();
|
||||||
|
|
||||||
auto styling = escape_html_entities(m_current_message_style.string_view());
|
auto styling = escape_html_entities(m_current_message_style.string_view());
|
||||||
m_current_message_style.clear();
|
m_current_message_style.clear();
|
||||||
|
|
||||||
if (log_level == JS::Console::LogLevel::Trace) {
|
if (log_level == JS::Console::LogLevel::Trace) {
|
||||||
auto trace = arguments.get<JS::Console::Trace>();
|
auto trace = arguments.get<JS::Console::Trace>();
|
||||||
StringBuilder html;
|
JS::ThrowableStringBuilder html(vm);
|
||||||
if (!trace.label.is_empty())
|
if (!trace.label.is_empty())
|
||||||
html.appendff("<span class='title' style='{}'>{}</span><br>", styling, escape_html_entities(trace.label));
|
MUST_OR_THROW_OOM(html.appendff("<span class='title' style='{}'>{}</span><br>", styling, escape_html_entities(trace.label)));
|
||||||
|
|
||||||
html.append("<span class='trace'>"sv);
|
MUST_OR_THROW_OOM(html.append("<span class='trace'>"sv));
|
||||||
for (auto& function_name : trace.stack)
|
for (auto& function_name : trace.stack)
|
||||||
html.appendff("-> {}<br>", escape_html_entities(function_name));
|
MUST_OR_THROW_OOM(html.appendff("-> {}<br>", escape_html_entities(function_name)));
|
||||||
html.append("</span>"sv);
|
MUST_OR_THROW_OOM(html.append("</span>"sv));
|
||||||
|
|
||||||
print_html(html.string_view());
|
print_html(html.string_view());
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
|
@ -153,35 +158,36 @@ JS::ThrowCompletionOr<JS::Value> WebContentConsoleClient::printer(JS::Console::L
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto output = DeprecatedString::join(' ', arguments.get<JS::MarkedVector<JS::Value>>());
|
auto output = TRY_OR_THROW_OOM(vm, String::join(' ', arguments.get<JS::MarkedVector<JS::Value>>()));
|
||||||
m_console.output_debug_message(log_level, output);
|
m_console.output_debug_message(log_level, output);
|
||||||
|
|
||||||
StringBuilder html;
|
JS::ThrowableStringBuilder html(vm);
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
case JS::Console::LogLevel::Debug:
|
case JS::Console::LogLevel::Debug:
|
||||||
html.appendff("<span class=\"debug\" style=\"{}\">(d) "sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span class=\"debug\" style=\"{}\">(d) "sv, styling));
|
||||||
break;
|
break;
|
||||||
case JS::Console::LogLevel::Error:
|
case JS::Console::LogLevel::Error:
|
||||||
html.appendff("<span class=\"error\" style=\"{}\">(e) "sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span class=\"error\" style=\"{}\">(e) "sv, styling));
|
||||||
break;
|
break;
|
||||||
case JS::Console::LogLevel::Info:
|
case JS::Console::LogLevel::Info:
|
||||||
html.appendff("<span class=\"info\" style=\"{}\">(i) "sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span class=\"info\" style=\"{}\">(i) "sv, styling));
|
||||||
break;
|
break;
|
||||||
case JS::Console::LogLevel::Log:
|
case JS::Console::LogLevel::Log:
|
||||||
html.appendff("<span class=\"log\" style=\"{}\"> "sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span class=\"log\" style=\"{}\"> "sv, styling));
|
||||||
break;
|
break;
|
||||||
case JS::Console::LogLevel::Warn:
|
case JS::Console::LogLevel::Warn:
|
||||||
case JS::Console::LogLevel::CountReset:
|
case JS::Console::LogLevel::CountReset:
|
||||||
html.appendff("<span class=\"warn\" style=\"{}\">(w) "sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span class=\"warn\" style=\"{}\">(w) "sv, styling));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
html.appendff("<span style=\"{}\">"sv, styling);
|
MUST_OR_THROW_OOM(html.appendff("<span style=\"{}\">"sv, styling));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.append(escape_html_entities(output));
|
MUST_OR_THROW_OOM(html.append(escape_html_entities(output)));
|
||||||
html.append("</span>"sv);
|
MUST_OR_THROW_OOM(html.append("</span>"sv));
|
||||||
print_html(html.string_view());
|
print_html(html.string_view());
|
||||||
|
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <LibJS/Runtime/ConsoleObject.h>
|
#include <LibJS/Runtime/ConsoleObject.h>
|
||||||
#include <LibJS/Runtime/JSONObject.h>
|
#include <LibJS/Runtime/JSONObject.h>
|
||||||
#include <LibJS/Runtime/StringPrototype.h>
|
#include <LibJS/Runtime/StringPrototype.h>
|
||||||
|
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||||
#include <LibJS/SourceTextModule.h>
|
#include <LibJS/SourceTextModule.h>
|
||||||
#include <LibLine/Editor.h>
|
#include <LibLine/Editor.h>
|
||||||
#include <LibMain/Main.h>
|
#include <LibMain/Main.h>
|
||||||
|
@ -531,16 +532,16 @@ public:
|
||||||
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
// 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer
|
||||||
virtual JS::ThrowCompletionOr<JS::Value> printer(JS::Console::LogLevel log_level, PrinterArguments arguments) override
|
virtual JS::ThrowCompletionOr<JS::Value> printer(JS::Console::LogLevel log_level, PrinterArguments arguments) override
|
||||||
{
|
{
|
||||||
DeprecatedString indent = DeprecatedString::repeated(" "sv, m_group_stack_depth);
|
auto indent = TRY_OR_THROW_OOM(*g_vm, String::repeated(' ', m_group_stack_depth * 2));
|
||||||
|
|
||||||
if (log_level == JS::Console::LogLevel::Trace) {
|
if (log_level == JS::Console::LogLevel::Trace) {
|
||||||
auto trace = arguments.get<JS::Console::Trace>();
|
auto trace = arguments.get<JS::Console::Trace>();
|
||||||
StringBuilder builder;
|
JS::ThrowableStringBuilder builder(*g_vm);
|
||||||
if (!trace.label.is_empty())
|
if (!trace.label.is_empty())
|
||||||
builder.appendff("{}\033[36;1m{}\033[0m\n", indent, trace.label);
|
MUST_OR_THROW_OOM(builder.appendff("{}\033[36;1m{}\033[0m\n", indent, trace.label));
|
||||||
|
|
||||||
for (auto& function_name : trace.stack)
|
for (auto& function_name : trace.stack)
|
||||||
builder.appendff("{}-> {}\n", indent, function_name);
|
MUST_OR_THROW_OOM(builder.appendff("{}-> {}\n", indent, function_name));
|
||||||
|
|
||||||
outln("{}", builder.string_view());
|
outln("{}", builder.string_view());
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
|
@ -553,7 +554,7 @@ public:
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto output = DeprecatedString::join(' ', arguments.get<JS::MarkedVector<JS::Value>>());
|
auto output = TRY_OR_THROW_OOM(*g_vm, String::join(' ', arguments.get<JS::MarkedVector<JS::Value>>()));
|
||||||
#ifdef AK_OS_SERENITY
|
#ifdef AK_OS_SERENITY
|
||||||
m_console.output_debug_message(log_level, output);
|
m_console.output_debug_message(log_level, output);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue