mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:32:44 +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/StringConstructor.h> | ||||
| #include <LibJS/Runtime/Temporal/Duration.h> | ||||
| #include <LibJS/Runtime/ThrowableStringBuilder.h> | ||||
| 
 | ||||
| namespace JS { | ||||
| 
 | ||||
|  | @ -98,29 +99,37 @@ ThrowCompletionOr<Value> Console::trace() | |||
|     auto& execution_context_stack = vm.execution_context_stack(); | ||||
|     // NOTE: -2 to skip the console.trace() execution context
 | ||||
|     for (ssize_t i = execution_context_stack.size() - 2; i >= 0; --i) { | ||||
|         auto& function_name = execution_context_stack[i]->function_name; | ||||
|         trace.stack.append(function_name.is_empty() ? "<anonymous>" : function_name); | ||||
|         auto const& function_name = execution_context_stack[i]->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.
 | ||||
|     if (vm.argument_count() > 0) { | ||||
|         StringBuilder builder; | ||||
|         auto data = vm_arguments(); | ||||
|         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 »).
 | ||||
|     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
 | ||||
| ThrowCompletionOr<Value> Console::count() | ||||
| { | ||||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 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.
 | ||||
|     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]).
 | ||||
|     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 »).
 | ||||
|     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) | ||||
|         TRY(m_client->logger(LogLevel::Count, concat_as_vector)); | ||||
|     return js_undefined(); | ||||
|  | @ -151,7 +160,7 @@ ThrowCompletionOr<Value> Console::count_reset() | |||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 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.
 | ||||
|     auto& map = m_counters; | ||||
|  | @ -164,10 +173,10 @@ ThrowCompletionOr<Value> Console::count_reset() | |||
|     else { | ||||
|         // 1. Let message be a string without any formatting specifiers indicating generically
 | ||||
|         //    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 »);
 | ||||
|         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) | ||||
|             TRY(m_client->logger(LogLevel::CountReset, message_as_vector)); | ||||
|     } | ||||
|  | @ -212,9 +221,9 @@ ThrowCompletionOr<Value> Console::assert_() | |||
|         // 3. Otherwise:
 | ||||
|         else { | ||||
|             // 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.
 | ||||
|             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
 | ||||
| ThrowCompletionOr<Value> Console::group() | ||||
| { | ||||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 1. Let group be a new group.
 | ||||
|     Group group; | ||||
| 
 | ||||
|     // 2. If data is not empty, let groupLabel be the result of Formatter(data).
 | ||||
|     DeprecatedString group_label; | ||||
|     String group_label {}; | ||||
|     auto data = vm_arguments(); | ||||
|     if (!data.is_empty()) { | ||||
|         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.
 | ||||
|     else { | ||||
|         group_label = "Group"; | ||||
|         group_label = TRY_OR_THROW_OOM(vm, String::from_utf8("Group"sv)); | ||||
|     } | ||||
| 
 | ||||
|     // 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
 | ||||
| ThrowCompletionOr<Value> Console::group_collapsed() | ||||
| { | ||||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 1. Let group be a new group.
 | ||||
|     Group group; | ||||
| 
 | ||||
|     // 2. If data is not empty, let groupLabel be the result of Formatter(data).
 | ||||
|     DeprecatedString group_label; | ||||
|     String group_label {}; | ||||
|     auto data = vm_arguments(); | ||||
|     if (!data.is_empty()) { | ||||
|         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.
 | ||||
|     else { | ||||
|         group_label = "Group"; | ||||
|         group_label = TRY_OR_THROW_OOM(vm, String::from_utf8("Group"sv)); | ||||
|     } | ||||
| 
 | ||||
|     // 3. Incorporate groupLabel as a label for group.
 | ||||
|  | @ -312,14 +325,17 @@ ThrowCompletionOr<Value> Console::time() | |||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 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
 | ||||
|     //    a warning to the console indicating that a timer with label `label` has already been started.
 | ||||
|     if (m_timer_table.contains(label)) { | ||||
|         if (m_client) { | ||||
|             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))); | ||||
|         } | ||||
|         return js_undefined(); | ||||
|  | @ -336,7 +352,7 @@ ThrowCompletionOr<Value> Console::time_log() | |||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 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.
 | ||||
| 
 | ||||
|  | @ -347,7 +363,10 @@ ThrowCompletionOr<Value> Console::time_log() | |||
|     if (maybe_start_time == m_timer_table.end()) { | ||||
|         if (m_client) { | ||||
|             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))); | ||||
|         } | ||||
|         return js_undefined(); | ||||
|  | @ -358,12 +377,12 @@ ThrowCompletionOr<Value> Console::time_log() | |||
|     auto duration = TRY(format_time_since(start_time)); | ||||
| 
 | ||||
|     // 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.
 | ||||
|     MarkedVector<Value> data { vm.heap() }; | ||||
|     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) | ||||
|         data.append(vm.argument(i)); | ||||
| 
 | ||||
|  | @ -379,7 +398,7 @@ ThrowCompletionOr<Value> Console::time_end() | |||
|     auto& vm = realm().vm(); | ||||
| 
 | ||||
|     // 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.
 | ||||
| 
 | ||||
|  | @ -390,7 +409,10 @@ ThrowCompletionOr<Value> Console::time_end() | |||
|     if (maybe_start_time == m_timer_table.end()) { | ||||
|         if (m_client) { | ||||
|             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))); | ||||
|         } | ||||
|         return js_undefined(); | ||||
|  | @ -404,12 +426,12 @@ ThrowCompletionOr<Value> Console::time_end() | |||
|     auto duration = TRY(format_time_since(start_time)); | ||||
| 
 | ||||
|     // 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 »).
 | ||||
|     if (m_client) { | ||||
|         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))); | ||||
|     } | ||||
|     return js_undefined(); | ||||
|  | @ -427,7 +449,7 @@ MarkedVector<Value> Console::vm_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) { | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| 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(); | ||||
|     StringBuilder builder; | ||||
|     ThrowableStringBuilder builder(vm); | ||||
| 
 | ||||
|     for (auto const& item : values) { | ||||
|         if (!builder.is_empty()) | ||||
|             builder.append(' '); | ||||
|         builder.append(TRY(item.to_deprecated_string(vm))); | ||||
|             MUST_OR_THROW_OOM(builder.append(' ')); | ||||
| 
 | ||||
|         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 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 append = [&](StringBuilder& builder, auto format, auto... number) { | ||||
|     auto append = [&](ThrowableStringBuilder& builder, auto format, auto number) -> ThrowCompletionOr<void> { | ||||
|         if (!builder.is_empty()) | ||||
|             builder.append(' '); | ||||
|         builder.appendff(format, number...); | ||||
|             MUST_OR_THROW_OOM(builder.append(' ')); | ||||
|         MUST_OR_THROW_OOM(builder.appendff(format, number)); | ||||
|         return {}; | ||||
|     }; | ||||
|     StringBuilder builder; | ||||
| 
 | ||||
|     ThrowableStringBuilder builder(vm); | ||||
| 
 | ||||
|     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) | ||||
|         append(builder, "{:.0} hour(s)"sv, duration.hours); | ||||
|         MUST_OR_THROW_OOM(append(builder, "{:.0} hour(s)"sv, duration.hours)); | ||||
|     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) { | ||||
|         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
 | ||||
|  | @ -539,7 +567,7 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val | |||
|         return 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.
 | ||||
|     auto current = (args.size() > 1) ? args[1] : js_undefined(); | ||||
|  | @ -621,19 +649,19 @@ ThrowCompletionOr<MarkedVector<Value>> ConsoleClient::formatter(MarkedVector<Val | |||
|         // 6. TODO: process %c
 | ||||
|         else if (specifier == "%c"sv) { | ||||
|             // 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 {}); | ||||
|         } | ||||
| 
 | ||||
|         // 7. If any of the previous steps set converted, replace specifier in target with converted.
 | ||||
|         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.
 | ||||
|     MarkedVector<Value> result { vm.heap() }; | ||||
|     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) | ||||
|         result.unchecked_append(args[i]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <AK/Function.h> | ||||
| #include <AK/HashMap.h> | ||||
| #include <AK/Noncopyable.h> | ||||
| #include <AK/String.h> | ||||
| #include <AK/Vector.h> | ||||
| #include <LibCore/ElapsedTimer.h> | ||||
| #include <LibJS/Forward.h> | ||||
|  | @ -45,12 +46,12 @@ public: | |||
|     }; | ||||
| 
 | ||||
|     struct Group { | ||||
|         DeprecatedString label; | ||||
|         String label; | ||||
|     }; | ||||
| 
 | ||||
|     struct Trace { | ||||
|         DeprecatedString label; | ||||
|         Vector<DeprecatedString> stack; | ||||
|         String label; | ||||
|         Vector<String> stack; | ||||
|     }; | ||||
| 
 | ||||
|     explicit Console(Realm&); | ||||
|  | @ -61,8 +62,8 @@ public: | |||
| 
 | ||||
|     MarkedVector<Value> vm_arguments(); | ||||
| 
 | ||||
|     HashMap<DeprecatedString, unsigned>& counters() { return m_counters; } | ||||
|     HashMap<DeprecatedString, unsigned> const& counters() const { return m_counters; } | ||||
|     HashMap<String, unsigned>& counters() { return m_counters; } | ||||
|     HashMap<String, unsigned> const& counters() const { return m_counters; } | ||||
| 
 | ||||
|     ThrowCompletionOr<Value> debug(); | ||||
|     ThrowCompletionOr<Value> error(); | ||||
|  | @ -81,18 +82,18 @@ public: | |||
|     ThrowCompletionOr<Value> time_log(); | ||||
|     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; | ||||
| 
 | ||||
| private: | ||||
|     ThrowCompletionOr<DeprecatedString> value_vector_to_deprecated_string(MarkedVector<Value> const&); | ||||
|     ThrowCompletionOr<DeprecatedString> format_time_since(Core::ElapsedTimer timer); | ||||
|     ThrowCompletionOr<String> value_vector_to_string(MarkedVector<Value> const&); | ||||
|     ThrowCompletionOr<String> format_time_since(Core::ElapsedTimer timer); | ||||
| 
 | ||||
|     Realm& m_realm; | ||||
|     ConsoleClient* m_client { nullptr }; | ||||
| 
 | ||||
|     HashMap<DeprecatedString, unsigned> m_counters; | ||||
|     HashMap<DeprecatedString, Core::ElapsedTimer> m_timer_table; | ||||
|     HashMap<String, unsigned> m_counters; | ||||
|     HashMap<String, Core::ElapsedTimer> m_timer_table; | ||||
|     Vector<Group> m_group_stack; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,9 @@ | |||
| 
 | ||||
| #include <LibJS/Heap/MarkedVector.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> | ||||
| 
 | ||||
| namespace Web::HTML { | ||||
|  | @ -31,16 +34,18 @@ void WorkerDebugConsoleClient::end_group() | |||
| // 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) | ||||
| { | ||||
|     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) { | ||||
|         auto trace = arguments.get<JS::Console::Trace>(); | ||||
|         StringBuilder builder; | ||||
|         JS::ThrowableStringBuilder builder(vm); | ||||
|         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) | ||||
|             builder.appendff("{}-> {}\n", indent, function_name); | ||||
|             MUST_OR_THROW_OOM(builder.appendff("{}-> {}\n", indent, function_name)); | ||||
| 
 | ||||
|         dbgln("{}", builder.string_view()); | ||||
|         return JS::js_undefined(); | ||||
|  | @ -53,7 +58,7 @@ JS::ThrowCompletionOr<JS::Value> WorkerDebugConsoleClient::printer(JS::Console:: | |||
|         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); | ||||
| 
 | ||||
|     switch (log_level) { | ||||
|  |  | |||
|  | @ -12,6 +12,9 @@ | |||
| #include <LibJS/MarkupGenerator.h> | ||||
| #include <LibJS/Runtime/AbstractOperations.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/Scripting/ClassicScript.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
 | ||||
| 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()); | ||||
|     m_current_message_style.clear(); | ||||
| 
 | ||||
|     if (log_level == JS::Console::LogLevel::Trace) { | ||||
|         auto trace = arguments.get<JS::Console::Trace>(); | ||||
|         StringBuilder html; | ||||
|         JS::ThrowableStringBuilder html(vm); | ||||
|         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) | ||||
|             html.appendff("-> {}<br>", escape_html_entities(function_name)); | ||||
|         html.append("</span>"sv); | ||||
|             MUST_OR_THROW_OOM(html.appendff("-> {}<br>", escape_html_entities(function_name))); | ||||
|         MUST_OR_THROW_OOM(html.append("</span>"sv)); | ||||
| 
 | ||||
|         print_html(html.string_view()); | ||||
|         return JS::js_undefined(); | ||||
|  | @ -153,35 +158,36 @@ JS::ThrowCompletionOr<JS::Value> WebContentConsoleClient::printer(JS::Console::L | |||
|         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); | ||||
| 
 | ||||
|     StringBuilder html; | ||||
|     JS::ThrowableStringBuilder html(vm); | ||||
|     switch (log_level) { | ||||
|     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; | ||||
|     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; | ||||
|     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; | ||||
|     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; | ||||
|     case JS::Console::LogLevel::Warn: | ||||
|     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; | ||||
|     default: | ||||
|         html.appendff("<span style=\"{}\">"sv, styling); | ||||
|         MUST_OR_THROW_OOM(html.appendff("<span style=\"{}\">"sv, styling)); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     html.append(escape_html_entities(output)); | ||||
|     html.append("</span>"sv); | ||||
|     MUST_OR_THROW_OOM(html.append(escape_html_entities(output))); | ||||
|     MUST_OR_THROW_OOM(html.append("</span>"sv)); | ||||
|     print_html(html.string_view()); | ||||
| 
 | ||||
|     return JS::js_undefined(); | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include <LibJS/Runtime/ConsoleObject.h> | ||||
| #include <LibJS/Runtime/JSONObject.h> | ||||
| #include <LibJS/Runtime/StringPrototype.h> | ||||
| #include <LibJS/Runtime/ThrowableStringBuilder.h> | ||||
| #include <LibJS/SourceTextModule.h> | ||||
| #include <LibLine/Editor.h> | ||||
| #include <LibMain/Main.h> | ||||
|  | @ -531,16 +532,16 @@ public: | |||
|     // 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 | ||||
|     { | ||||
|         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) { | ||||
|             auto trace = arguments.get<JS::Console::Trace>(); | ||||
|             StringBuilder builder; | ||||
|             JS::ThrowableStringBuilder builder(*g_vm); | ||||
|             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) | ||||
|                 builder.appendff("{}-> {}\n", indent, function_name); | ||||
|                 MUST_OR_THROW_OOM(builder.appendff("{}-> {}\n", indent, function_name)); | ||||
| 
 | ||||
|             outln("{}", builder.string_view()); | ||||
|             return JS::js_undefined(); | ||||
|  | @ -553,7 +554,7 @@ public: | |||
|             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 | ||||
|         m_console.output_debug_message(log_level, output); | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn